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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CamBooth/CamBooth.App/MainWindow.xaml.cs b/src/CamBooth/CamBooth.App/MainWindow.xaml.cs
new file mode 100644
index 0000000..e955f77
--- /dev/null
+++ b/src/CamBooth/CamBooth.App/MainWindow.xaml.cs
@@ -0,0 +1,51 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+using CamBooth.App.Core.Logging;
+using CamBooth.App.DebugConsole;
+using CamBooth.App.LiveView;
+
+namespace CamBooth.App;
+
+///
+/// Interaction logic for MainWindow.xaml
+///
+public partial class MainWindow : Window
+{
+ private readonly Logger _logger;
+
+ private bool _isDebugConsoleVisible;
+
+ public MainWindow(Logger logger)
+ {
+ this._logger = logger;
+ InitializeComponent();
+ logger.LogInfo("MainWindow initialized");
+ ToggleDebugConsole();
+ }
+
+ private void NavToLiveView(object sender, RoutedEventArgs e)
+ {
+ MainFrame.Navigate(new LiveViewPage());
+ }
+
+ private void ToggleDebugConsole(object sender, RoutedEventArgs e)
+ {
+ this.ToggleDebugConsole();
+ }
+
+ private void ToggleDebugConsole()
+ {
+ if (_isDebugConsoleVisible)
+ {
+ this.DebugFrame.ClearValue(Frame.ContentProperty);
+ }
+ else
+ {
+ this.DebugFrame.Navigate(new DebugConsolePage());
+ }
+
+ this._isDebugConsoleVisible = !this._isDebugConsoleVisible;
+ }
+}
\ No newline at end of file
diff --git a/src/CamBooth/CamBooth.sln b/src/CamBooth/CamBooth.sln
index 1a471c5..5b8b0fc 100644
--- a/src/CamBooth/CamBooth.sln
+++ b/src/CamBooth/CamBooth.sln
@@ -1,10 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CamBooth.App", "CamBooth.App\CamBooth.App.csproj", "{C0EEB2D6-5C1D-4245-AFDC-A7640E386573}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EDSDKLib", "EDSDKLib\EDSDKLib.csproj", "{15E99248-6161-46A4-9183-609CA62406A6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C0EEB2D6-5C1D-4245-AFDC-A7640E386573}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C0EEB2D6-5C1D-4245-AFDC-A7640E386573}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C0EEB2D6-5C1D-4245-AFDC-A7640E386573}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C0EEB2D6-5C1D-4245-AFDC-A7640E386573}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15E99248-6161-46A4-9183-609CA62406A6}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {15E99248-6161-46A4-9183-609CA62406A6}.Debug|Any CPU.Build.0 = Debug|x86
+ {15E99248-6161-46A4-9183-609CA62406A6}.Release|Any CPU.ActiveCfg = Release|x86
+ {15E99248-6161-46A4-9183-609CA62406A6}.Release|Any CPU.Build.0 = Release|x86
EndGlobalSection
EndGlobal
diff --git a/src/CamBooth/CamBooth.sln.DotSettings.user b/src/CamBooth/CamBooth.sln.DotSettings.user
new file mode 100644
index 0000000..af2df7e
--- /dev/null
+++ b/src/CamBooth/CamBooth.sln.DotSettings.user
@@ -0,0 +1,12 @@
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
\ No newline at end of file
diff --git a/src/CamBooth/EDSDKLib/API/Base/Camera.cs b/src/CamBooth/EDSDKLib/API/Base/Camera.cs
new file mode 100644
index 0000000..51f1a71
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Base/Camera.cs
@@ -0,0 +1,1569 @@
+using System;
+using System.IO;
+using System.Threading;
+using EOSDigital.SDK;
+using FileAccess = EOSDigital.SDK.FileAccess;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace EOSDigital.API
+{
+ ///
+ /// Represents a physical camera and provides methods to control it
+ ///
+ public class Camera : IDisposable
+ {
+ #region Events
+
+ ///
+ /// The SDK object event
+ ///
+ protected event SDKObjectEventHandler SDKObjectEvent;
+ ///
+ /// The SDK progress event
+ ///
+ protected event SDKProgressCallback SDKProgressCallbackEvent;
+ ///
+ /// The SDK property event
+ ///
+ protected event SDKPropertyEventHandler SDKPropertyEvent;
+ ///
+ /// The SDK state event
+ ///
+ protected event SDKStateEventHandler SDKStateEvent;
+
+ ///
+ /// Fires if any process reports progress
+ ///
+ public event ProgressHandler ProgressChanged;
+ ///
+ /// Fires if the live view image is updated
+ ///
+ public event LiveViewUpdate LiveViewUpdated;
+ ///
+ /// Fires if an image is ready for download.
+ /// Call the or method to get the image or to cancel.
+ ///
+ public event DownloadHandler DownloadReady;
+ ///
+ /// Fires if a property has changed
+ ///
+ public event PropertyChangeHandler PropertyChanged;
+ ///
+ /// Fires if a state has changed
+ ///
+ public event StateChangeHandler StateChanged;
+ ///
+ /// Fires if an object has changed
+ ///
+ public event ObjectChangeHandler ObjectChanged;
+ ///
+ /// This event fires if the camera is disconnected or has shut down
+ ///
+ public event CameraUpdateHandler CameraHasShutdown;
+ ///
+ /// This event fires when the live view loop has ended
+ ///
+ public event CameraUpdateHandler LiveViewStopped;
+
+ #endregion
+
+ #region Variables
+
+ ///
+ /// Info about this camera (can be retrieved without an open session)
+ ///
+ protected DeviceInfo Info;
+ ///
+ /// Thread for executing SDK commands
+ ///
+ protected STAThread MainThread;
+
+ ///
+ /// Pointer to the SDKs camera object
+ ///
+ public IntPtr Reference
+ {
+ get { return CamRef; }
+ }
+ ///
+ /// An ID for the camera object in this session. It's essentially the pointer of the Canon SDK camera object
+ ///
+ public long ID
+ {
+ get { return CamRef.ToInt64(); }
+ }
+ ///
+ /// States if a session with this camera is open
+ ///
+ public bool SessionOpen
+ {
+ get { return _SessionOpen; }
+ protected set { _SessionOpen = value; }
+ }
+ ///
+ /// States if the camera is disposed. If true, it can't be used anymore
+ ///
+ public bool IsDisposed
+ {
+ get { return _IsDisposed; }
+ }
+ ///
+ /// The name of the camera (can be retrieved without an open session)
+ ///
+ public string DeviceName
+ {
+ get { return Info.DeviceDescription; }
+ }
+ ///
+ /// The name of the port the camera is connected to (can be retrieved without an open session)
+ ///
+ public string PortName
+ {
+ get { return Info.PortName; }
+ }
+ ///
+ /// States if the live view is running on the computer or not
+ ///
+ public bool IsLiveViewOn
+ {
+ get { return _IsLiveViewOn; }
+ protected set { _IsLiveViewOn = value; }
+ }
+ ///
+ /// States if Record property is available for this camera
+ ///
+ public bool IsRecordAvailable
+ {
+ get { return _IsRecordAvailable; }
+ }
+
+ ///
+ /// Pointer to the camera object
+ ///
+ private IntPtr CamRef;
+ ///
+ /// Variable to let the live view download loop continue or stop
+ ///
+ private bool KeepLVAlive = false;
+ ///
+ /// Thread for the live view download routine
+ ///
+ private Thread LVThread;
+ ///
+ /// Field for the public property
+ ///
+ private bool _IsLiveViewOn;
+ ///
+ /// Field for the public property
+ ///
+ private bool _IsDisposed;
+ ///
+ /// Field for the public property
+ ///
+ private bool _SessionOpen;
+ ///
+ /// Field for the public property
+ ///
+ private bool _IsRecordAvailable;
+ ///
+ /// Object to set a lock around starting/stopping the live view thread
+ ///
+ private readonly object lvThreadLockObj = new object();
+ ///
+ /// States if a film should be downloaded after filming or not
+ ///
+ private bool saveFilm;
+ ///
+ /// States if the live view should be shown on the PC while filming
+ ///
+ private bool useFilmingPcLv = false;
+
+ #endregion
+
+ #region Init/Open/Close/Dispose
+
+ ///
+ /// Constructor
+ ///
+ /// Reference to the camera object
+ /// Pointer to camera is zero
+ /// An SDK call failed
+ internal protected Camera(IntPtr camRef)
+ {
+ if (camRef == IntPtr.Zero) throw new ArgumentNullException(nameof(camRef));
+ CamRef = camRef;
+ MainThread = new STAThread();
+ MainThread.Start();
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsGetDeviceInfo(CamRef, out Info)));
+ }
+
+ ///
+ /// Destructor
+ ///
+ ~Camera()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Open a new session with camera
+ ///
+ /// Camera is disposed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void OpenSession()
+ {
+ CheckState(false);
+
+ if (!SessionOpen)
+ {
+ MainThread.Invoke(() =>
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsOpenSession(CamRef));
+
+ //Check if Record is available
+ int property;
+ _IsRecordAvailable = CanonSDK.GetPropertyData(CamRef, PropertyID.Record, 0, out property) == ErrorCode.OK;
+
+ //Subscribe to events
+ SDKStateEvent += new SDKStateEventHandler(Camera_SDKStateEvent);
+ SDKPropertyEvent += new SDKPropertyEventHandler(Camera_SDKPropertyEvent);
+ SDKProgressCallbackEvent += new SDKProgressCallback(Camera_SDKProgressCallbackEvent);
+ SDKObjectEvent += new SDKObjectEventHandler(Camera_SDKObjectEvent);
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetCameraStateEventHandler(CamRef, StateEventID.All, SDKStateEvent, CamRef));
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetObjectEventHandler(CamRef, ObjectEventID.All, SDKObjectEvent, CamRef));
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetPropertyEventHandler(CamRef, PropertyEventID.All, SDKPropertyEvent, CamRef));
+
+ SessionOpen = true;
+ });
+ }
+ }
+
+ ///
+ /// Close session with camera
+ ///
+ /// Camera is disposed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void CloseSession()
+ {
+ CheckState(false);
+
+ if (SessionOpen)
+ {
+ //Unsubscribe from all events
+ UnsubscribeEvents();
+
+ //If the live view is on, stop it
+ if (IsLiveViewOn)
+ {
+ KeepLVAlive = false;
+ LVThread.Join(5000);
+ }
+
+ MainThread.Invoke(() =>
+ {
+ //Close the session with the camera
+ ErrorHandler.CheckError(this, CanonSDK.EdsCloseSession(CamRef));
+ SessionOpen = false;
+ });
+ }
+ }
+
+ ///
+ /// Releases all data and closes session
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases all data and closes session
+ ///
+ /// True if called from Dispose, false if called from the finalizer/destructor
+ protected virtual void Dispose(bool managed)
+ {
+ if (!IsDisposed)
+ {
+ //Unsubscribe from all events
+ UnsubscribeEvents();
+
+ //If the live view is on, stop it
+ if (IsLiveViewOn)
+ {
+ KeepLVAlive = false;
+ LVThread.Join();
+ }
+ IsLiveViewOn = false;
+
+ MainThread.Invoke(() =>
+ {
+ if (CanonAPI.IsSDKInitialized)
+ {
+ //If it's open, close the session
+ if (SessionOpen) CanonSDK.EdsCloseSession(CamRef);
+ //Release the camera
+ CanonSDK.EdsRelease(CamRef);
+ }
+ _IsDisposed = true;
+ });
+ //Shutdown the main camera thread
+ MainThread.Shutdown();
+ }
+ }
+
+ ///
+ /// Unsubscribes all camera events from this class and the SDK
+ ///
+ private void UnsubscribeEvents()
+ {
+ SDKStateEvent -= Camera_SDKStateEvent;
+ SDKPropertyEvent -= Camera_SDKPropertyEvent;
+ SDKProgressCallbackEvent -= Camera_SDKProgressCallbackEvent;
+ SDKObjectEvent -= Camera_SDKObjectEvent;
+
+ if (CanonAPI.IsSDKInitialized)
+ {
+ MainThread.Invoke(() =>
+ {
+ //Clear callbacks from Canon SDK
+ CanonSDK.EdsSetCameraStateEventHandler(CamRef, StateEventID.All, null, CamRef);
+ CanonSDK.EdsSetObjectEventHandler(CamRef, ObjectEventID.All, null, CamRef);
+ CanonSDK.EdsSetPropertyEventHandler(CamRef, PropertyEventID.All, null, CamRef);
+ });
+ }
+ }
+
+ #endregion
+
+ #region SDK Eventhandling
+
+ private ErrorCode Camera_SDKObjectEvent(ObjectEventID inEvent, IntPtr inRef, IntPtr inContext)
+ {
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try
+ {
+ var DownloadReadyEvent = DownloadReady;
+ if (inEvent == ObjectEventID.DirItemRequestTransfer && DownloadReadyEvent != null)
+ {
+ DownloadReadyEvent(this, new DownloadInfo(inRef));
+ }
+ else if (inEvent == ObjectEventID.DirItemCreated && saveFilm && DownloadReadyEvent != null)
+ {
+ saveFilm = false;
+ DownloadReadyEvent(this, new DownloadInfo(inRef));
+ }
+ }
+ catch (Exception ex) { if (!IsDisposed && !ErrorHandler.ReportError(this, ex)) throw; }
+
+ ObjectChanged?.Invoke(this, inEvent, inRef);
+ });
+ return ErrorCode.OK;
+ }
+
+ private ErrorCode Camera_SDKProgressCallbackEvent(int inPercent, IntPtr inContext, ref bool outCancel)
+ {
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try { ProgressChanged?.Invoke(this, inPercent); }
+ catch (Exception ex) { if (!IsDisposed && !ErrorHandler.ReportError(this, ex)) throw; }
+ });
+ return ErrorCode.OK;
+ }
+
+ private ErrorCode Camera_SDKPropertyEvent(PropertyEventID inEvent, PropertyID inPropertyID, int inParameter, IntPtr inContext)
+ {
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try
+ {
+ if (inPropertyID == PropertyID.Evf_OutputDevice || inPropertyID == PropertyID.Record)
+ {
+ lock (lvThreadLockObj)
+ {
+ EvfOutputDevice outDevice = GetEvf_OutputDevice();
+ Recording recordState = IsRecordAvailable ? ((Recording)GetInt32Setting(PropertyID.Record)) : Recording.Off;
+
+ if (outDevice == EvfOutputDevice.PC || (recordState == Recording.Ready && outDevice == EvfOutputDevice.Filming) ||
+ (useFilmingPcLv && recordState == Recording.On && (outDevice == EvfOutputDevice.Filming || outDevice == EvfOutputDevice.Camera)))
+ {
+ if (!KeepLVAlive)
+ {
+ KeepLVAlive = true;
+ LVThread = STAThread.CreateThread(DownloadEvf);
+ LVThread.Start();
+ }
+ }
+ else if (KeepLVAlive) { KeepLVAlive = false; }
+ }
+ }
+ }
+ catch (Exception ex) { if (!IsDisposed && !ErrorHandler.ReportError(this, ex)) throw; }
+
+ PropertyChanged?.Invoke(this, inEvent, inPropertyID, inParameter);
+ });
+ return ErrorCode.OK;
+ }
+
+ private ErrorCode Camera_SDKStateEvent(StateEventID inEvent, int inParameter, IntPtr inContext)
+ {
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try
+ {
+ if (inEvent == StateEventID.Shutdown)
+ {
+ SessionOpen = false;
+ Dispose(true);
+ CameraHasShutdown?.Invoke(this);
+ }
+ }
+ catch (Exception ex) { if (!IsDisposed && !ErrorHandler.ReportError(this, ex)) throw; }
+
+ StateChanged?.Invoke(this, inEvent, inParameter);
+ });
+ return ErrorCode.OK;
+ }
+
+ #endregion
+
+ #region Methods
+
+ #region Take Photo
+
+ ///
+ /// Takes a photo with the current camera settings with the TakePicture command
+ ///
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhoto()
+ {
+ CheckState();
+ SendCommand(CameraCommand.TakePicture);
+ }
+
+ ///
+ /// Takes a photo with the current camera settings asynchronously with the TakePicture command
+ ///
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhotoAsync()
+ {
+ CheckState();
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try { SendCommand(CameraCommand.TakePicture); }
+ catch (Exception ex) { if (!ErrorHandler.ReportError(this, ex)) throw; }
+ });
+ }
+
+ ///
+ /// Takes a photo with the current camera settings with the PressShutterButton command
+ ///
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhotoShutter()
+ {
+ CheckState();
+ MainThread.Invoke(() =>
+ {
+ SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.Completely);
+ SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.OFF);
+ });
+ }
+
+ ///
+ /// Takes a photo with the current camera settings asynchronously with the PressShutterButton command
+ ///
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhotoShutterAsync()
+ {
+ CheckState();
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try
+ {
+ MainThread.Invoke(() =>
+ {
+ SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.Completely);
+ SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.OFF);
+ });
+ }
+ catch (Exception ex) { if (!ErrorHandler.ReportError(this, ex)) throw; }
+ });
+ }
+
+ ///
+ /// Takes a bulb photo with the current camera settings.
+ /// The Tv camera value must be set to Bulb before calling this
+ ///
+ /// The time in ms for how long the shutter will be open
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhotoBulb(int bulbTime)
+ {
+ CheckState();
+
+ SendCommand(CameraCommand.BulbStart);
+ Thread.Sleep(bulbTime);
+ SendCommand(CameraCommand.BulbEnd);
+ }
+
+ ///
+ /// Takes a bulb photo with the current camera settings asynchronously.
+ /// The Tv camera value must be set to Bulb before calling this
+ ///
+ /// The time in ms for how long the shutter will be open
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void TakePhotoBulbAsync(int bulbTime)
+ {
+ CheckState();
+
+ ThreadPool.QueueUserWorkItem((state) =>
+ {
+ try
+ {
+ SendCommand(CameraCommand.BulbStart);
+ Thread.Sleep(bulbTime);
+ SendCommand(CameraCommand.BulbEnd);
+ }
+ catch (Exception ex) { if (!ErrorHandler.ReportError(this, ex)) throw; }
+ });
+ }
+
+ #endregion
+
+ #region File Handling
+
+ ///
+ /// Downloads a file to given directory with the filename in the
+ ///
+ /// The that is provided by the event
+ /// The directory where the file will be saved to
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// The DownloadInfo is null
+ public void DownloadFile(DownloadInfo Info, string directory)
+ {
+ CheckState();
+ if (Info == null) throw new ArgumentNullException(nameof(Info));
+ if (directory == null || string.IsNullOrEmpty(directory.Trim())) directory = ".";
+
+ string currentFile = Path.Combine(directory, Info.FileName);
+ if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
+ DownloadToFile(Info, currentFile);
+ }
+
+ ///
+ /// Downloads a file into a stream
+ ///
+ /// The that is provided by the event
+ /// The stream containing the file data
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// The DownloadInfo is null
+ public Stream DownloadFile(DownloadInfo Info)
+ {
+ CheckState();
+ if (Info == null) throw new ArgumentNullException(nameof(Info));
+ return DownloadToStream(Info);
+ }
+
+ ///
+ /// Cancels the download of an image
+ ///
+ /// The DownloadInfo that is provided by the "" event
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// The DownloadInfo is null
+ /// An SDK call failed
+ public void CancelDownload(DownloadInfo Info)
+ {
+ CheckState();
+ if (Info == null) throw new ArgumentNullException(nameof(Info));
+
+ MainThread.Invoke(() =>
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsDownloadCancel(Info.Reference));
+ ErrorHandler.CheckError(this, CanonSDK.EdsRelease(Info.Reference));
+ });
+ }
+
+ ///
+ /// Gets all volumes available on the camera
+ ///
+ /// An array of CameraFileEntries that are the volumes
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public CameraFileEntry[] GetAllVolumes()
+ {
+ CheckState();
+ return GetAllVolumesSub();
+ }
+
+ ///
+ /// Gets all volumes, folders and files existing on the camera
+ ///
+ /// A that contains all the information
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public CameraFileEntry GetAllEntries()
+ {
+ CheckState();
+ return GetAllEntriesSub();
+ }
+
+ ///
+ /// Gets all images saved on the cameras memory card(s)
+ ///
+ /// An array of CameraFileEntries that are the images
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public CameraFileEntry[] GetAllImages()
+ {
+ CheckState();
+ return GetAllImagesSub();
+ }
+
+ ///
+ /// Formats a given camera volume. Get the available volumes with
+ /// Warning: All data on this volume will be lost!
+ ///
+ /// The volume that will get formatted
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// CameraFileEntry is not a volume
+ /// An SDK call failed
+ public void FormatVolume(CameraFileEntry volume)
+ {
+ CheckState();
+ if (!volume.IsVolume) throw new ArgumentException("CameraFileEntry must be a volume");
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsFormatVolume(volume.Reference)));
+ }
+
+ ///
+ /// Downloads all given files into a folder. To get all images on the camera, use
+ /// or for all files
+ ///
+ /// Note: All given CameraFileEntries will be disposed after this.
+ /// Call or to get valid entries again.
+ ///
+ ///
+ /// The path to the folder where the files will be saved to
+ /// The files that will be downloaded
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void DownloadFiles(string folderpath, CameraFileEntry[] files)
+ {
+ CheckState();
+ if (files == null) return;
+ if (folderpath == null || string.IsNullOrEmpty(folderpath.Trim())) folderpath = ".";
+ if (!Directory.Exists(folderpath)) Directory.CreateDirectory(folderpath);
+
+ for (int i = 0; i < files.Length; i++)
+ {
+ if (!files[i].IsFolder && !files[i].IsDisposed)
+ {
+ var info = new DownloadInfo(files[i].Reference);
+ string CurrentFile = Path.Combine(folderpath, info.FileName);
+ DownloadToFile(info, CurrentFile);
+ }
+ }
+ }
+
+ ///
+ /// Deletes all given files on the camera.
+ /// To get all images on the camera, use or for all files
+ /// Warning: All given files will be lost!
+ ///
+ /// The images that will be deleted
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ public void DeleteFiles(CameraFileEntry[] files)
+ {
+ CheckState();
+ if (files == null || files.Length == 0) return;
+
+ for (int i = 0; i < files.Length; i++)
+ {
+ if (!files[i].IsFolder && !files[i].IsDisposed)
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsDeleteDirectoryItem(files[i].Reference));
+ files[i].IsDisposed = true;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Other
+
+ ///
+ /// Tells the camera how much space is available on the host PC
+ ///
+ /// Bytes per HD sector
+ /// Number of free clusters on the HD
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void SetCapacity(int bytesPerSector, int numberOfFreeClusters)
+ {
+ CheckState();
+ MainThread.Invoke(() =>
+ {
+ Capacity capacity = new Capacity(numberOfFreeClusters, bytesPerSector, true);
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetCapacity(CamRef, capacity));
+ });
+ }
+
+ ///
+ /// Locks or unlocks the camera UI
+ ///
+ /// True to lock, false to unlock
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void UILock(bool lockState)
+ {
+ if (lockState) SendStatusCommand(CameraStatusCommand.UILock);
+ else SendStatusCommand(CameraStatusCommand.UIUnLock);
+ }
+
+ ///
+ /// Gets the list of possible values for the current camera to set.
+ /// Only the PropertyIDs "AEModeSelect", "ISO", "Av", "Tv", "MeteringMode" and "ExposureCompensation" are allowed.
+ ///
+ /// The property ID
+ /// A list of available values for the given property ID
+ public CameraValue[] GetSettingsList(PropertyID propId)
+ {
+ CheckState();
+
+ if (propId == PropertyID.AEModeSelect || propId == PropertyID.ISO || propId == PropertyID.Av || propId == PropertyID.Tv
+ || propId == PropertyID.MeteringMode || propId == PropertyID.ExposureCompensation)
+ {
+ CameraValue[] vals = null;
+ PropertyDesc des = default(PropertyDesc);
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsGetPropertyDesc(CamRef, propId, out des)));
+ vals = new CameraValue[des.NumElements];
+ for (int i = 0; i < vals.Length; i++) vals[i] = new CameraValue(des.PropDesc[i], propId);
+ return vals;
+ }
+ else throw new ArgumentException($"Method cannot be used with Property ID {propId}");
+ }
+
+ ///
+ /// Sends a command safely to the camera
+ ///
+ /// The command
+ /// Additional parameter
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void SendCommand(CameraCommand command, int inParam = 0)
+ {
+ CheckState();
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsSendCommand(CamRef, command, inParam)));
+ }
+
+ ///
+ /// Sends a Status Command to the camera
+ ///
+ /// The command
+ /// Additional parameter
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void SendStatusCommand(CameraStatusCommand command, int inParam = 0)
+ {
+ CheckState();
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsSendStatusCommand(CamRef, command, inParam)));
+ }
+
+ ///
+ /// Starts the live view
+ ///
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void StartLiveView()
+ {
+ CheckState();
+ if (!IsLiveViewOn) SetSetting(PropertyID.Evf_OutputDevice, (int)EvfOutputDevice.PC);
+ }
+
+ ///
+ /// Stops the live view
+ ///
+ /// If true, the live view is shut off, if false, the live view will be shown on the cameras screen
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void StopLiveView(bool LVOff = true)
+ {
+ CheckState();
+ if (LVOff) SetSetting(PropertyID.Evf_OutputDevice, (int)EvfOutputDevice.Off);
+ else SetSetting(PropertyID.Evf_OutputDevice, (int)EvfOutputDevice.Camera);
+ }
+
+ ///
+ /// Starts recording a video
+ /// Note: The camera has to be set into filming mode before using this (usually a physical switch on the camera)
+ /// This works only on cameras that support filming
+ ///
+ /// If true, the live view will be transferred to the computer otherwise it's shown on the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// The camera is not in film mode
+ /// An SDK call failed
+ public void StartFilming(bool PCLiveview)
+ {
+ CheckState();
+
+ Recording state = (Recording)GetInt32Setting(PropertyID.Record);
+ if (state != Recording.On)
+ {
+ if (state != Recording.Ready) throw new InvalidOperationException("The camera is not ready to film. The Record property has to be Recording.Ready");
+ useFilmingPcLv = PCLiveview;
+ //When recording videos, it has to be saved on the camera internal memory
+ SetSetting(PropertyID.SaveTo, (int)SaveTo.Camera);
+ //Start the video recording
+ SetSetting(PropertyID.Record, (int)Recording.On);
+ }
+ }
+
+ ///
+ /// Stops recording a video
+ ///
+ /// If true, the event will fire as soon as the video file is created on the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void StopFilming(bool saveFilm)
+ {
+ StopFilming(saveFilm, true);
+ }
+
+ ///
+ /// Stops recording a video
+ ///
+ /// If true, the event will fire as soon as the video file is created on the camera
+ /// If true, the PC live view will stop and will only be shown on the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void StopFilming(bool saveFilm, bool stopLiveView)
+ {
+ CheckState();
+
+ Recording state = (Recording)GetInt32Setting(PropertyID.Record);
+ if (state == Recording.On)
+ {
+ this.saveFilm = saveFilm;
+ //Stop video recording
+ SetSetting(PropertyID.Record, (int)Recording.Off);
+ useFilmingPcLv = false;
+ if (IsLiveViewOn && stopLiveView) StopLiveView(false);
+ }
+ }
+
+ #endregion
+
+ #region Set Settings
+
+ ///
+ /// Sets a value for the given property ID
+ ///
+ /// The property ID
+ /// The value which will be set
+ /// Additional property information
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void SetSetting(PropertyID propID, object value, int inParam = 0)
+ {
+ CheckState();
+
+ MainThread.Invoke(() =>
+ {
+ int propsize;
+ DataType proptype;
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetPropertySize(CamRef, propID, inParam, out proptype, out propsize));
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetPropertyData(CamRef, propID, inParam, propsize, value));
+ });
+ }
+
+ ///
+ /// Sets a string value for the given property ID
+ ///
+ /// The property ID
+ /// The value which will be set
+ /// Additional property information
+ /// The maximum length of the string
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public void SetSetting(PropertyID propID, string value, int inParam = 0, int MAX = 32)
+ {
+ CheckState();
+
+ if (value == null) value = string.Empty;
+ if (value.Length > MAX - 1) value = value.Substring(0, MAX - 1);
+
+ byte[] propBytes = System.Text.Encoding.ASCII.GetBytes(value + '\0');
+ MainThread.Invoke(() =>
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetPropertyData(CamRef,
+ propID, inParam, propBytes.Length, propBytes));
+ });
+ }
+
+ ///
+ /// Sets a struct value for the given property ID
+ ///
+ /// The property ID
+ /// The value which will be set
+ /// Additional property information
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ [Obsolete("Use SetSetting directly because internally it does the same")]
+ public void SetStructSetting(PropertyID propID, T value, int inParam = 0) where T : struct
+ {
+ SetSetting(propID, value, inParam);
+ }
+
+ #endregion
+
+ #region Get Settings
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public bool GetBoolSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ bool property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public byte GetByteSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ byte property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public short GetInt16Setting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ short property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ [CLSCompliant(false)]
+ public ushort GetUInt16Setting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ ushort property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ [CLSCompliant(false)]
+ public uint GetUInt32Setting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ uint property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public int GetInt32Setting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ int property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a string
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public string GetStringSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ string property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+
+ ///
+ /// Gets the current setting of given property ID as a integer array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public bool[] GetBoolArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ bool[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a integer array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public short[] GetInt16ArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ short[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a integer array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public int[] GetInt32ArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ int[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a integer array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public byte[] GetByteArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ byte[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a unsigned integer array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ [CLSCompliant(false)]
+ public uint[] GetUInt32ArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ uint[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a rational array
+ ///
+ /// The property ID
+ /// Additional property information
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public Rational[] GetRationalArrSetting(PropertyID propID, int inParam = 0)
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ Rational[] data;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out data));
+ return data;
+ });
+ }
+
+ ///
+ /// Gets the current setting of given property ID as a struct
+ ///
+ /// The property ID
+ /// Additional property information
+ /// One of the EDSDK structs
+ /// The current setting of the camera
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ /// An SDK call failed
+ public T GetStructSetting(PropertyID propID, int inParam = 0) where T : struct
+ {
+ CheckState();
+
+ return MainThread.Invoke(() =>
+ {
+ T property;
+ ErrorHandler.CheckError(this, CanonSDK.GetPropertyData(CamRef, propID, inParam, out property));
+ return property;
+ });
+ }
+
+
+ ///
+ /// There is an overflow bug in the SDK that messes up the Evf_OutputDevice property.
+ /// With this method you can get the adjusted and correct value.
+ ///
+ /// The current output device of the live view
+ public EvfOutputDevice GetEvf_OutputDevice()
+ {
+ int value = GetInt32Setting(PropertyID.Evf_OutputDevice);
+
+ unchecked
+ {
+ if ((value > 2147483600 || value < -2147483640) && value != (int)0xFFFFFFFF) return (EvfOutputDevice)(int.MinValue + value);
+ else return (EvfOutputDevice)value;
+ };
+ }
+
+ #endregion
+
+ #region Subroutines
+
+ ///
+ /// Downloads live view images and the live view metadata continuously
+ ///
+ private void DownloadEvf()
+ {
+ if (IsLiveViewOn) return;
+
+ try
+ {
+ //Create variables
+ IntPtr evfImageRef = IntPtr.Zero;
+ ErrorCode err;
+
+ //Create stream
+ using (var stream = new SDKStream(0))
+ {
+ IsLiveViewOn = true;
+
+ //Run live view
+ while (KeepLVAlive)
+ {
+ //Get live view image
+ lock (STAThread.ExecLock)
+ {
+ err = CanonSDK.EdsCreateEvfImageRef(stream.Reference, out evfImageRef);
+ if (err == ErrorCode.OK) err = CanonSDK.EdsDownloadEvfImage(CamRef, evfImageRef);
+ }
+
+ //Check for errors
+ if (err == ErrorCode.OBJECT_NOTREADY) { continue; }
+ else if (err != ErrorCode.OK) { ErrorHandler.CheckError(err); continue; }
+
+ //Release current evf image
+ CanonSDK.EdsRelease(evfImageRef);
+
+ //Set stream position back to zero
+ stream.Position = 0;
+
+ //Update live view
+ LiveViewUpdated?.Invoke(this, stream);
+ }
+ }
+ }
+ catch (Exception ex) { if (ex is ThreadAbortException || !ErrorHandler.ReportError(this, ex)) throw; }
+ finally
+ {
+ IsLiveViewOn = false;
+ ThreadPool.QueueUserWorkItem((state) => LiveViewStopped?.Invoke(this));
+ }
+ }
+
+ ///
+ /// Downloads any data from the camera to the computer
+ ///
+ /// The info about the object that will get downloaded
+ /// The pointer to the stream where the data will be loaded into
+ /// An SDK call failed
+ protected void DownloadData(DownloadInfo Info, IntPtr stream)
+ {
+ MainThread.Invoke(() =>
+ {
+ try
+ {
+ //Set the progress callback
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetProgressCallback(stream, SDKProgressCallbackEvent, ProgressOption.Periodically, Info.Reference));
+ //Check which SDK version is used and download the data with the correct method
+ if (CanonSDK.IsVerGE34) ErrorHandler.CheckError(this, CanonSDK.EdsDownload(Info.Reference, Info.Size64, stream));
+ else ErrorHandler.CheckError(this, CanonSDK.EdsDownload(Info.Reference, Info.Size, stream));
+ }
+ finally
+ {
+ //Release all data
+ ErrorHandler.CheckError(this, CanonSDK.EdsDownloadComplete(Info.Reference));
+ ErrorHandler.CheckError(this, CanonSDK.EdsRelease(Info.Reference));
+ }
+ });
+ }
+
+ ///
+ /// Downloads any data from the camera to the computer in a file
+ ///
+ /// The info about the object that will get downloaded
+ /// The path with filename to where the data will be saved to
+ /// An SDK call failed
+ protected void DownloadToFile(DownloadInfo Info, string filepath)
+ {
+ using (var stream = new SDKStream(filepath, FileCreateDisposition.CreateAlways, FileAccess.ReadWrite))
+ {
+ DownloadData(Info, stream.Reference);
+ }
+ }
+
+ ///
+ /// Downloads any data from the camera to the computer into a
+ ///
+ /// The info about the object that will get downloaded
+ /// A containing the downloaded data
+ /// An SDK call failed
+ protected Stream DownloadToStream(DownloadInfo Info)
+ {
+ SDKStream stream = new SDKStream(Info.Size64);
+ DownloadData(Info, stream.Reference);
+ stream.Position = 0;
+ return stream;
+ }
+
+ ///
+ /// Gets information about camera file entries recursively
+ ///
+ /// Pointer to the current file object
+ /// An array of file entries
+ /// An SDK call failed
+ protected CameraFileEntry[] GetChildren(IntPtr ptr)
+ {
+ int ChildCount;
+ lock (STAThread.ExecLock) { ErrorHandler.CheckError(this, CanonSDK.EdsGetChildCount(ptr, out ChildCount)); }
+ if (ChildCount > 0)
+ {
+ CameraFileEntry[] MainEntry = new CameraFileEntry[ChildCount];
+ for (int i = 0; i < ChildCount; i++)
+ {
+ MainEntry[i] = GetChild(ptr, i);
+
+ if (MainEntry[i].IsFolder)
+ {
+ CameraFileEntry[] retval = GetChildren(MainEntry[i].Reference);
+ if (retval != null) MainEntry[i].Entries = retval;
+ }
+ }
+ return MainEntry;
+ }
+ else return null;
+ }
+
+ ///
+ /// Gets information about children of a folder in the cameras file system
+ ///
+ /// Pointer to the folder
+ /// Index of the child in the folder
+ /// A camera file entry of this child
+ /// An SDK call failed
+ protected CameraFileEntry GetChild(IntPtr ptr, int index)
+ {
+ return MainThread.Invoke(() =>
+ {
+ IntPtr ChildPtr;
+ DirectoryItemInfo ChildInfo;
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetChildAtIndex(ptr, index, out ChildPtr));
+ ErrorHandler.CheckError(this, CanonSDK.GetDirectoryItemInfo(ChildPtr, out ChildInfo));
+
+ CameraFileEntry outEntry = new CameraFileEntry(ChildPtr, ChildInfo.FileName, ChildInfo.IsFolder, false);
+ if (!outEntry.IsFolder)
+ {
+ using (var stream = new SDKStream(0))
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsDownloadThumbnail(ChildPtr, stream.Reference));
+ outEntry.SetThumb(stream.Reference);
+ }
+ }
+ return outEntry;
+ });
+ }
+
+ ///
+ /// Checks if the camera and SDK state is valid
+ ///
+ /// If true, it checks if the session is open
+ /// Camera is disposed
+ /// Session is closed
+ /// Canon SDK is not initialized
+ protected void CheckState(bool checkSession = true)
+ {
+ if (IsDisposed) throw new ObjectDisposedException(nameof(Camera) + ID);
+ if (checkSession && !SessionOpen) throw new CameraSessionException("Session is closed");
+ if (!CanonAPI.IsSDKInitialized) throw new SDKStateException("Canon SDK is not initialized");
+ }
+
+ ///
+ /// Creates a bool value from an integer. 1 == true, else == false
+ ///
+ /// The integer value
+ /// The bool value
+ protected bool GetBool(int val)
+ {
+ return val == 1;
+ }
+
+ ///
+ /// Gets all volumes, folders and files existing on the camera
+ ///
+ /// A that contains all the information
+ /// An SDK call failed
+ protected CameraFileEntry GetAllEntriesSub()
+ {
+ CameraFileEntry MainEntry = new CameraFileEntry(IntPtr.Zero, DeviceName, true, false);
+ CameraFileEntry[] VolumeEntries = GetAllVolumesSub();
+
+ for (int i = 0; i < VolumeEntries.Length; i++) VolumeEntries[i].Entries = GetChildren(VolumeEntries[i].Reference);
+
+ MainEntry.Entries = VolumeEntries;
+ return MainEntry;
+ }
+
+ ///
+ /// Gets all images saved on the cameras memory card(s)
+ ///
+ /// An array of CameraFileEntries that are the images
+ /// An SDK call failed
+ protected CameraFileEntry[] GetAllImagesSub()
+ {
+ CameraFileEntry[] volumes = GetAllVolumesSub();
+ List ImageList = new List();
+
+ for (int i = 0; i < volumes.Length; i++)
+ {
+ int ChildCount;
+ lock (STAThread.ExecLock) { ErrorHandler.CheckError(this, CanonSDK.EdsGetChildCount(volumes[i].Reference, out ChildCount)); }
+ CameraFileEntry[] ventries = new CameraFileEntry[0];
+
+ for (int j = 0; j < ChildCount; j++)
+ {
+ CameraFileEntry entry = GetChild(volumes[i].Reference, j);
+ if (entry.IsFolder && entry.Name == "DCIM") { ventries = GetChildren(entry.Reference); break; }
+ }
+
+ foreach (CameraFileEntry ve in ventries) { if (ve.IsFolder && ve.Entries != null) ImageList.AddRange(ve.Entries.Where(t => !t.IsFolder)); }
+ }
+
+ return ImageList.ToArray();
+ }
+
+ ///
+ /// Checks for all volumes available on the camera.
+ ///
+ /// An array of CameraFileEntries where each represents a volume (Note: content of volumes is not read)
+ /// An SDK call failed
+ protected CameraFileEntry[] GetAllVolumesSub()
+ {
+ int VolumeCount;
+ IntPtr ChildPtr;
+ VolumeInfo vinfo;
+ List VolumeEntries = new List();
+
+ MainThread.Invoke(() =>
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetChildCount(CamRef, out VolumeCount));
+
+ for (int i = 0; i < VolumeCount; i++)
+ {
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetChildAtIndex(CamRef, i, out ChildPtr));
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetVolumeInfo(ChildPtr, out vinfo));
+ if (vinfo.VolumeLabel != "HDD") VolumeEntries.Add(new CameraFileEntry(ChildPtr, "Volume" + i + "(" + vinfo.VolumeLabel + ")", true, true));
+ }
+ });
+
+ return VolumeEntries.ToArray();
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Base/CanonAPI.cs b/src/CamBooth/EDSDKLib/API/Base/CanonAPI.cs
new file mode 100644
index 0000000..e5b70ce
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Base/CanonAPI.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Threading;
+using EOSDigital.SDK;
+using Size = EOSDigital.SDK.Size;
+
+namespace EOSDigital.API
+{
+ ///
+ /// Handles camera connections
+ ///
+ public class CanonAPI : IDisposable
+ {
+ #region Events
+
+ ///
+ /// Fires if a new camera is added
+ ///
+ public event CameraAddedHandler CameraAdded;
+ ///
+ /// The SDK camera added delegate
+ ///
+ protected static SDKCameraAddedHandler CameraAddedEvent;
+
+ private ErrorCode CanonAPI_CameraAddedEvent(IntPtr inContext)
+ {
+ ThreadPool.QueueUserWorkItem((state) => CameraAdded?.Invoke(this));
+ return ErrorCode.OK;
+ }
+
+ #endregion
+
+ #region Variables
+
+ ///
+ /// States if the SDK is initialized or not
+ ///
+ public static bool IsSDKInitialized
+ {
+ get { return _IsSDKInitialized; }
+ }
+ ///
+ /// The main SDK thread where the event loop runs
+ ///
+ protected static STAThread MainThread;
+
+ ///
+ /// Field for the public property
+ ///
+ private static bool _IsSDKInitialized;
+ ///
+ /// States if the instance is disposed or not
+ ///
+ private bool IsDisposed;
+ ///
+ /// Number of instances of this class
+ ///
+ private static int RefCount = 0;
+ ///
+ /// Object to lock on to safely de- and increment the value
+ ///
+ private static readonly object InitLock = new object();
+ ///
+ /// List of currently connected cameras (since the last time GetCameraList got called)
+ ///
+ private static List CurrentCameras = new List();
+ ///
+ /// Object to lock on to safely add/remove cameras from the list
+ ///
+ private static readonly object CameraLock = new object();
+
+ #endregion
+
+ #region Init/Dispose
+
+ ///
+ /// Initializes the SDK
+ ///
+ public CanonAPI()
+ : this(false)
+ { }
+
+ ///
+ /// Initializes the SDK
+ ///
+ /// If true, the calling thread will be used as SDK main thread;
+ /// if false, a separate thread will be created
+ public CanonAPI(bool useCallingThread)
+ {
+ try
+ {
+ //Ensure that only one caller at a time can increase the counter
+ lock (InitLock)
+ {
+ //If no instance exists yet, initialize everything
+ if (RefCount == 0)
+ {
+ if (useCallingThread)
+ {
+ if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
+ throw new ThreadStateException("Calling thread must be in STA");
+ ErrorHandler.CheckError(this, CanonSDK.EdsInitializeSDK());
+ }
+ else
+ {
+ //Trying to trigger DllNotFoundException so it's not thrown
+ //in the event loop on a different thread:
+ CanonSDK.EdsRelease(IntPtr.Zero);
+
+ //Start the main thread where SDK will run on
+ MainThread = new ApiThread();
+ MainThread.Start();
+ //Initialize the SDK on the main thread
+ MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsInitializeSDK()));
+ }
+
+ CanonSDK.InitializeVersion();
+ //Subscribe to the CameraAdded event
+ CameraAddedEvent = new SDKCameraAddedHandler(CanonAPI_CameraAddedEvent);
+ ErrorHandler.CheckError(this, CanonSDK.EdsSetCameraAddedHandler(CameraAddedEvent, IntPtr.Zero));
+ _IsSDKInitialized = true;
+ }
+ RefCount++;
+ }
+ }
+ catch
+ {
+ IsDisposed = true;
+ if (MainThread?.IsRunning == true) MainThread.Shutdown();
+ throw;
+ }
+ }
+
+ ///
+ /// Destructor
+ ///
+ ~CanonAPI()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Terminates the SDK and disposes resources
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Terminates the SDK and disposes resources
+ ///
+ /// True if called from Dispose, false if called from the finalizer/destructor
+ protected virtual void Dispose(bool managed)
+ {
+ //Ensure that only one caller at a time can decrease the counter
+ lock (InitLock)
+ {
+ if (!IsDisposed)
+ {
+ //If it's the last instance, release everything
+ if (RefCount == 1)
+ {
+ _IsSDKInitialized = false;//Set beforehand because if an error happens, the SDK will be in an unstable state anyway
+
+ //Remove event handler for the CameraAdded event
+ ErrorCode err = CanonSDK.EdsSetCameraAddedHandler(null, IntPtr.Zero);
+ if (managed)
+ {
+ ErrorHandler.CheckError(this, err);
+ //Dispose all the connected cameras
+ CurrentCameras.ForEach(t => t.Dispose());
+ }
+ //Terminate the SDK
+ if (MainThread?.IsRunning == true) err = MainThread.Invoke(() => { return CanonSDK.EdsTerminateSDK(); });
+ //Close the main thread
+ if (MainThread?.IsRunning == true) MainThread.Shutdown();
+ if (managed) ErrorHandler.CheckError(this, err);
+ }
+ RefCount--;
+ IsDisposed = true;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Get a list of all cameras connected to the host.
+ /// If a camera has been connected previously, the same instance of the class is returned.
+ ///
+ /// A list of connected cameras
+ /// This instance has been disposed already
+ /// An SDK call failed
+ public List GetCameraList()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(nameof(CanonAPI));
+
+ //Ensure that only one caller at a time can access the camera list
+ lock (CameraLock)
+ {
+ //Get a list of camera pointers
+ IEnumerable ptrList = GetCameraPointerList();
+ List camList = new List();
+
+ //Find cameras that were connected before and add new ones
+ foreach (var ptr in ptrList)
+ {
+ var oldCam = CurrentCameras.FirstOrDefault(t => t.Reference == ptr);
+ if (oldCam != null && !oldCam.IsDisposed) camList.Add(oldCam); //Pointer exists already so we reuse it
+ else camList.Add(new Camera(ptr)); //Pointer does not exists yet, so we add it
+ }
+
+ //Ensure that cameras not connected anymore are disposed properly
+ var oldCameras = CurrentCameras.Where(t => !ptrList.Any(u => u == t.Reference));
+ foreach (var cam in oldCameras) { if (!cam.IsDisposed) cam.Dispose(); }
+
+ CurrentCameras.Clear();
+ CurrentCameras.AddRange(camList);
+ return camList;
+ }
+ }
+
+ ///
+ /// Get a list of all pointer of the cameras connected to the host
+ ///
+ /// A list of connected cameras as pointer
+ /// This instance has been disposed already
+ /// An SDK call failed
+ protected IEnumerable GetCameraPointerList()
+ {
+ if (IsDisposed) throw new ObjectDisposedException(nameof(CanonAPI));
+
+ IntPtr camlist;
+ //Get camera list
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetCameraList(out camlist));
+
+ //Get number of connected cameras
+ int camCount;
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetChildCount(camlist, out camCount));
+ List ptrList = new List();
+ for (int i = 0; i < camCount; i++)
+ {
+ //Get camera pointer
+ IntPtr cptr;
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetChildAtIndex(camlist, i, out cptr));
+ ptrList.Add(cptr);
+ }
+ //Release the list
+ ErrorHandler.CheckError(this, CanonSDK.EdsRelease(camlist));
+ return ptrList;
+ }
+
+ ///
+ /// Gets a thumbnail from a Raw or Jpg image
+ ///
+ /// Path to the image file
+ /// A thumbnail from the provided image file
+ public Bitmap GetFileThumb(string filepath)
+ {
+ //create a file stream to given file
+ using (var stream = new SDKStream(filepath, FileCreateDisposition.OpenExisting, FileAccess.Read))
+ {
+ //Create a thumbnail Bitmap from the stream
+ return GetImage(stream.Reference, ImageSource.Thumbnail);
+ }
+ }
+
+ ///
+ /// Gets a from an EDSDK pointer to an image (Jpg or Raw)
+ ///
+ /// Stream pointer to the image
+ /// The result image type
+ /// A image from the given stream pointer
+ protected Bitmap GetImage(IntPtr imgStream, ImageSource imageSource)
+ {
+ IntPtr imgRef = IntPtr.Zero;
+ IntPtr streamPointer = IntPtr.Zero;
+ ImageInfo imageInfo;
+
+ try
+ {
+ //create reference and get image info
+ ErrorHandler.CheckError(this, CanonSDK.EdsCreateImageRef(imgStream, out imgRef));
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetImageInfo(imgRef, imageSource, out imageInfo));
+
+ Size outputSize = new Size();
+ outputSize.Width = imageInfo.EffectiveRect.Width;
+ outputSize.Height = imageInfo.EffectiveRect.Height;
+ //calculate amount of data
+ int datalength = outputSize.Height * outputSize.Width * 3;
+ //create buffer that stores the image
+ byte[] buffer = new byte[datalength];
+ //create a stream to the buffer
+ using (var stream = new SDKStream(buffer))
+ {
+ //load image into the buffer
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetImage(imgRef, imageSource, TargetImageType.RGB, imageInfo.EffectiveRect, outputSize, stream.Reference));
+
+ //make BGR from RGB (System.Drawing (i.e. GDI+) uses BGR)
+ unsafe
+ {
+ byte tmp;
+ fixed (byte* pix = buffer)
+ {
+ for (long i = 0; i < datalength; i += 3)
+ {
+ tmp = pix[i]; //Save B value
+ pix[i] = pix[i + 2]; //Set B value with R value
+ pix[i + 2] = tmp; //Set R value with B value
+ }
+ }
+ }
+
+ //Get pointer to stream data
+ ErrorHandler.CheckError(this, CanonSDK.EdsGetPointer(stream.Reference, out streamPointer));
+ //Create bitmap with the data in the buffer
+ return new Bitmap(outputSize.Width, outputSize.Height, datalength, PixelFormat.Format24bppRgb, streamPointer);
+ }
+ }
+ finally
+ {
+ //Release all data
+ if (imgStream != IntPtr.Zero) ErrorHandler.CheckError(this, CanonSDK.EdsRelease(imgStream));
+ if (imgRef != IntPtr.Zero) ErrorHandler.CheckError(this, CanonSDK.EdsRelease(imgRef));
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/CamBooth/EDSDKLib/API/Helper/ApiThread.cs b/src/CamBooth/EDSDKLib/API/Helper/ApiThread.cs
new file mode 100644
index 0000000..83c494c
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/ApiThread.cs
@@ -0,0 +1,25 @@
+using EOSDigital.SDK;
+using System.Threading;
+
+namespace EOSDigital.API
+{
+ internal sealed class ApiThread : STAThread
+ {
+ protected override void WaitForNotification()
+ {
+ lock (threadLock1)
+ {
+ while (block1 && IsRunning)
+ {
+ Monitor.Wait(threadLock1, 0);
+ lock (ExecLock)
+ {
+ CanonSDK.EdsGetEvent();
+ Monitor.Wait(ExecLock, 40);
+ }
+ }
+ block1 = true;
+ }
+ }
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/CameraValue.cs b/src/CamBooth/EDSDKLib/API/Helper/CameraValue.cs
new file mode 100644
index 0000000..431d987
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/CameraValue.cs
@@ -0,0 +1,282 @@
+using EOSDigital.SDK;
+
+namespace EOSDigital.API
+{
+ ///
+ /// Stores a camera value
+ ///
+ public class CameraValue
+ {
+ ///
+ /// The value as a string
+ ///
+ public string StringValue { get; protected set; }
+ ///
+ /// The value as an UInt
+ ///
+ public int IntValue { get; protected set; }
+ ///
+ /// The value as a double
+ ///
+ public double DoubleValue { get; protected set; }
+ ///
+ /// The property ID of this value
+ ///
+ public PropertyID ValueType { get; protected set; }
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ protected CameraValue()
+ {
+ ValueType = PropertyID.Unknown;
+ StringValue = "N/A";
+ IntValue = unchecked((int)0xFFFFFFFF);
+ DoubleValue = 0.0;
+ }
+
+ ///
+ /// Creates a new camera value
+ ///
+ /// The value as a string
+ /// The property ID of the value
+ public CameraValue(string Value, PropertyID ValueType)
+ : this()
+ {
+ this.ValueType = ValueType;
+ StringValue = Value;
+ switch (ValueType)
+ {
+ case PropertyID.Av:
+ IntValue = AvValues.GetValue(Value).IntValue;
+ DoubleValue = AvValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.Tv:
+ IntValue = TvValues.GetValue(Value).IntValue;
+ DoubleValue = TvValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ISO:
+ IntValue = ISOValues.GetValue(Value).IntValue;
+ DoubleValue = ISOValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ColorTemperature:
+ int utmp;
+ IntValue = (int.TryParse(Value, out utmp)) ? utmp : 5600;
+ DoubleValue = utmp;
+ break;
+ case PropertyID.AEMode:
+ IntValue = AEModeValues.GetValue(Value).IntValue;
+ DoubleValue = AEModeValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.MeteringMode:
+ IntValue = MeteringModeValues.GetValue(Value).IntValue;
+ DoubleValue = MeteringModeValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ExposureCompensation:
+ IntValue = ExpCompValues.GetValue(Value).IntValue;
+ DoubleValue = ExpCompValues.GetValue(Value).DoubleValue;
+ break;
+ }
+ }
+
+ ///
+ /// Creates a new camera value
+ ///
+ /// The value as an uint
+ /// The property ID of the value
+ public CameraValue(int Value, PropertyID ValueType)
+ : this()
+ {
+ this.ValueType = ValueType;
+ IntValue = Value;
+ switch (ValueType)
+ {
+ case PropertyID.Av:
+ StringValue = AvValues.GetValue(Value).StringValue;
+ DoubleValue = AvValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.Tv:
+ StringValue = TvValues.GetValue(Value).StringValue;
+ DoubleValue = TvValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ISO:
+ StringValue = ISOValues.GetValue(Value).StringValue;
+ DoubleValue = ISOValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ColorTemperature:
+ StringValue = Value.ToString();
+ DoubleValue = Value;
+ break;
+ case PropertyID.AEMode:
+ StringValue = AEModeValues.GetValue(Value).StringValue;
+ DoubleValue = AEModeValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.MeteringMode:
+ StringValue = MeteringModeValues.GetValue(Value).StringValue;
+ DoubleValue = MeteringModeValues.GetValue(Value).DoubleValue;
+ break;
+ case PropertyID.ExposureCompensation:
+ StringValue = ExpCompValues.GetValue(Value).StringValue;
+ DoubleValue = ExpCompValues.GetValue(Value).DoubleValue;
+ break;
+ }
+ }
+
+ ///
+ /// Creates a new camera value
+ ///
+ /// The value as a double
+ /// The property ID of the value
+ public CameraValue(double Value, PropertyID ValueType)
+ : this()
+ {
+ this.ValueType = ValueType;
+ DoubleValue = Value;
+ switch (ValueType)
+ {
+ case PropertyID.Av:
+ StringValue = AvValues.GetValue(Value).StringValue;
+ IntValue = AvValues.GetValue(Value).IntValue;
+ break;
+ case PropertyID.Tv:
+ StringValue = TvValues.GetValue(Value).StringValue;
+ IntValue = TvValues.GetValue(Value).IntValue;
+ break;
+ case PropertyID.ISO:
+ StringValue = ISOValues.GetValue(Value).StringValue;
+ IntValue = ISOValues.GetValue(Value).IntValue;
+ break;
+ case PropertyID.ColorTemperature:
+ StringValue = Value.ToString("F0");
+ IntValue = (int)Value;
+ break;
+ case PropertyID.AEMode:
+ StringValue = AEModeValues.GetValue(Value).StringValue;
+ IntValue = AEModeValues.GetValue(Value).IntValue;
+ break;
+ case PropertyID.MeteringMode:
+ StringValue = MeteringModeValues.GetValue(Value).StringValue;
+ IntValue = MeteringModeValues.GetValue(Value).IntValue;
+ break;
+ case PropertyID.ExposureCompensation:
+ StringValue = ExpCompValues.GetValue(Value).StringValue;
+ IntValue = ExpCompValues.GetValue(Value).IntValue;
+ break;
+ }
+ }
+
+ internal CameraValue(string SValue, int IValue, double DValue)
+ {
+ ValueType = PropertyID.Unknown;
+ StringValue = SValue;
+ IntValue = IValue;
+ DoubleValue = DValue;
+ }
+
+ internal CameraValue(string SValue, int IValue, double DValue, PropertyID ValueType)
+ {
+ this.ValueType = ValueType;
+ StringValue = SValue;
+ IntValue = IValue;
+ DoubleValue = DValue;
+ }
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(CameraValue x, CameraValue y)
+ {
+ // If both are null, or both are same instance, return true.
+ if (object.ReferenceEquals(x, y)) return true;
+
+ // If one is null, but not both, return false.
+ if ((object)x == null || (object)y == null) return false;
+
+ return x.IntValue == y.IntValue && x.ValueType == y.ValueType;
+ }
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(CameraValue x, CameraValue y)
+ {
+ return !(x == y);
+ }
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ // If objects have different types, return false.
+ if (obj.GetType() != GetType()) return false;
+
+ // If both are null, or both are same instance, return true.
+ if (object.ReferenceEquals(this, obj)) return true;
+
+ CameraValue cv = obj as CameraValue;
+ if (cv == null) return false;
+
+ return IntValue == cv.IntValue && ValueType == cv.ValueType;
+ }
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ IntValue.GetHashCode();
+ hash *= 16777619 ^ ValueType.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Implicitly converts the camera value to an int
+ ///
+ /// The camera value to convert
+ /// The int representing the camera value
+ public static implicit operator int(CameraValue x)
+ {
+ return x.IntValue;
+ }
+
+ ///
+ /// Implicitly converts the camera value to a string
+ ///
+ /// The camera value to convert
+ /// The string representing the camera value
+ public static implicit operator string(CameraValue x)
+ {
+ return x.StringValue;
+ }
+
+ ///
+ /// Implicitly converts the camera value to a double
+ ///
+ /// The camera value to convert
+ /// The double representing the camera value
+ public static implicit operator double(CameraValue x)
+ {
+ return x.DoubleValue;
+ }
+
+ ///
+ /// Returns a string that represents the current .
+ ///
+ /// A string that represents the current .
+ public override string ToString()
+ {
+ return StringValue;
+ }
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/Delegates.cs b/src/CamBooth/EDSDKLib/API/Helper/Delegates.cs
new file mode 100644
index 0000000..7467a71
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/Delegates.cs
@@ -0,0 +1,69 @@
+using System;
+using System.IO;
+using EOSDigital.SDK;
+
+namespace EOSDigital.API
+{
+ ///
+ /// A delegate for progress
+ ///
+ /// The sender of this event
+ /// The progress. A value between 0 and 100
+ public delegate void ProgressHandler(object sender, int progress);
+ ///
+ /// A delegate to pass a stream
+ ///
+ /// The sender of this event
+ /// An image embedded in a stream
+ public delegate void LiveViewUpdate(Camera sender, Stream img);
+ ///
+ /// A delegate to report an available download
+ ///
+ /// The sender of this event
+ /// The data for the download
+ public delegate void DownloadHandler(Camera sender, DownloadInfo Info);
+ ///
+ /// A delegate for property changes
+ ///
+ /// The sender of this event
+ /// The property event ID
+ /// The property ID
+ /// A parameter for additional information
+ public delegate void PropertyChangeHandler(Camera sender, PropertyEventID eventID, PropertyID propID, int parameter);
+ ///
+ /// A delegate for camera state changes
+ ///
+ /// The sender of this event
+ /// The state event ID
+ /// A parameter for additional information
+ public delegate void StateChangeHandler(Camera sender, StateEventID eventID, int parameter);
+ ///
+ /// A delegate for property changes
+ ///
+ /// The sender of this event
+ /// The object event ID
+ /// A pointer to the object that has changed
+ public delegate void ObjectChangeHandler(Camera sender, ObjectEventID eventID, IntPtr reference);
+ ///
+ /// A delegate to inform of an added camera
+ ///
+ /// The sender of this event
+ public delegate void CameraAddedHandler(CanonAPI sender);
+ ///
+ /// A delegate to inform of a change of a camera
+ ///
+ /// The sender of this event
+ public delegate void CameraUpdateHandler(Camera sender);
+ ///
+ /// A delegate to inform of SDK exceptions
+ ///
+ /// The sender of this event
+ /// The SDK exception
+ public delegate void SDKExceptionHandler(object sender, ErrorCode ex);
+ ///
+ /// A delegate to inform of exceptions
+ ///
+ /// The sender of this event
+ /// The exception
+ public delegate void GeneralExceptionHandler(object sender, Exception ex);
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/ExceptionHandling.cs b/src/CamBooth/EDSDKLib/API/Helper/ExceptionHandling.cs
new file mode 100644
index 0000000..98e6c6a
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/ExceptionHandling.cs
@@ -0,0 +1,421 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using EOSDigital.SDK;
+
+namespace EOSDigital.API
+{
+ ///
+ /// An Exception that happened while handling the Canon SDK
+ ///
+ [Serializable]
+ public sealed class SDKException : Exception
+ {
+ ///
+ /// The specific SDK error code that happened
+ ///
+ public ErrorCode Error { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ public SDKException()
+ {
+ Error = ErrorCode.INTERNAL_ERROR;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified error code
+ ///
+ /// The SDK error code of the error that happened
+ public SDKException(ErrorCode Error)
+ : base(Error.ToString())
+ {
+ this.Error = Error;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified error message
+ ///
+ /// The error message that explains the reason for the exception.
+ public SDKException(string message)
+ : base(message)
+ {
+ Error = ErrorCode.INTERNAL_ERROR;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and a reference to the inner exception that is the cause of
+ /// this exception
+ ///
+ /// The error message that explains the reason for the exception
+ /// The exception that is the cause of the current exception, or a null reference
+ /// (Nothing in Visual Basic) if no inner exception is specified
+ public SDKException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ Error = ErrorCode.INTERNAL_ERROR;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified error message and error code
+ ///
+ /// The SDK error code of the error that happened
+ /// The error message that explains the reason for the exception
+ public SDKException(string message, ErrorCode Error)
+ : base(message)
+ {
+ this.Error = Error;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message, error code and a reference to the inner exception that is the cause of
+ /// this exception
+ ///
+ /// The error message that explains the reason for the exception
+ /// The SDK error code of the error that happened
+ /// The exception that is the cause of the current exception, or a null reference
+ /// (Nothing in Visual Basic) if no inner exception is specified.
+ public SDKException(string message, ErrorCode Error, Exception innerException)
+ : base(message, innerException)
+ {
+ this.Error = Error;
+ }
+
+ ///
+ /// Initializes a new instance of the class with serialized data.
+ ///
+ /// The that holds the serialized
+ /// object data about the exception being thrown.
+ /// The that contains contextual
+ /// information about the source or destination.
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ private SDKException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ Error = (ErrorCode)info.GetUInt32("Error");
+ }
+
+ ///
+ /// When overridden in a derived class, sets the
+ /// with information about the exception.
+ ///
+ /// The
+ /// that holds the serialized object data about the exception being thrown
+ /// The
+ /// that contains contextual information about the source or destination.
+ /// The info parameter is a null reference
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ info.AddValue("Error", Error);
+
+ base.GetObjectData(info, context);
+ }
+ }
+
+ ///
+ /// An Exception that states a problem with the session state of the camera
+ ///
+ [Serializable]
+ public sealed class CameraSessionException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class
+ ///
+ public CameraSessionException()
+ { }
+
+ ///
+ /// Initializes a new instance of the class with a specified error message
+ ///
+ /// The error message that explains the reason for the exception.
+ public CameraSessionException(string message)
+ : base(message)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and a reference to the inner exception that is the cause of
+ /// this exception
+ ///
+ /// The error message that explains the reason for the exception
+ /// The exception that is the cause of the current exception, or a null reference
+ /// (Nothing in Visual Basic) if no inner exception is specified
+ public CameraSessionException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with serialized data.
+ ///
+ /// The that holds the serialized
+ /// object data about the exception being thrown.
+ /// The that contains contextual
+ /// information about the source or destination.
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ private CameraSessionException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+
+ ///
+ /// When overridden in a derived class, sets the
+ /// with information about the exception.
+ ///
+ /// The
+ /// that holds the serialized object data about the exception being thrown
+ /// The
+ /// that contains contextual information about the source or destination.
+ /// The info parameter is a null reference
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ base.GetObjectData(info, context);
+ }
+ }
+
+ ///
+ /// An Exception that states a problem with the state of the Canon SDK
+ ///
+ [Serializable]
+ public sealed class SDKStateException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class
+ ///
+ public SDKStateException()
+ { }
+
+ ///
+ /// Initializes a new instance of the class with a specified error message
+ ///
+ /// The error message that explains the reason for the exception.
+ public SDKStateException(string message)
+ : base(message)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and a reference to the inner exception that is the cause of
+ /// this exception
+ ///
+ /// The error message that explains the reason for the exception
+ /// The exception that is the cause of the current exception, or a null reference
+ /// (Nothing in Visual Basic) if no inner exception is specified
+ public SDKStateException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with serialized data.
+ ///
+ /// The that holds the serialized
+ /// object data about the exception being thrown.
+ /// The that contains contextual
+ /// information about the source or destination.
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ private SDKStateException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+
+ ///
+ /// When overridden in a derived class, sets the
+ /// with information about the exception.
+ ///
+ /// The
+ /// that holds the serialized object data about the exception being thrown
+ /// The
+ /// that contains contextual information about the source or destination.
+ /// The info parameter is a null reference
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ base.GetObjectData(info, context);
+ }
+ }
+
+ ///
+ /// An Exception that happened while executing on an STA thread
+ ///
+ [Serializable]
+ public sealed class ExecutionException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class with a specified error message
+ ///
+ /// The error message that explains the reason for the exception.
+ public ExecutionException(string message)
+ : base(message)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with a reference to
+ /// the inner exception that is the cause of this exception
+ ///
+ /// The error message that explains the reason for the exception
+ /// The exception that is the cause of the current exception, or a null reference
+ /// (Nothing in Visual Basic) if no inner exception is specified
+ public ExecutionException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with serialized data.
+ ///
+ /// The that holds the serialized
+ /// object data about the exception being thrown.
+ /// The that contains contextual
+ /// information about the source or destination.
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ private ExecutionException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+
+ ///
+ /// When overridden in a derived class, sets the
+ /// with information about the exception.
+ ///
+ /// The
+ /// that holds the serialized object data about the exception being thrown
+ /// The
+ /// that contains contextual information about the source or destination.
+ /// The info parameter is a null reference
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ base.GetObjectData(info, context);
+ }
+ }
+
+ ///
+ /// Handles errors and provides events for errors (e.g. focus problems or general exceptions)
+ ///
+ public static class ErrorHandler
+ {
+ ///
+ /// If an error happened, that does not break the program, this event is fired (e.g. a focus error)
+ ///
+ public static event SDKExceptionHandler NonSevereErrorHappened;
+ ///
+ /// If an error happened on a thread that does not fall into the non-severe category, this event is fired
+ ///
+ public static event GeneralExceptionHandler SevereErrorHappened;
+ ///
+ /// List of all non-severe errors. Items can be added or removed.
+ ///
+ public static List NonSevereErrors { get; private set; }
+
+ static ErrorHandler()
+ {
+ NonSevereErrors = new List()
+ {
+ ErrorCode.TAKE_PICTURE_AF_NG,
+ ErrorCode.TAKE_PICTURE_CARD_NG,
+ ErrorCode.TAKE_PICTURE_CARD_PROTECT_NG,
+ ErrorCode.TAKE_PICTURE_LV_REL_PROHIBIT_MODE_NG,
+ ErrorCode.TAKE_PICTURE_MIRROR_UP_NG,
+ ErrorCode.TAKE_PICTURE_MOVIE_CROP_NG,
+ ErrorCode.TAKE_PICTURE_NO_CARD_NG,
+ ErrorCode.TAKE_PICTURE_NO_LENS_NG,
+ ErrorCode.TAKE_PICTURE_SENSOR_CLEANING_NG,
+ ErrorCode.TAKE_PICTURE_SILENCE_NG,
+ ErrorCode.TAKE_PICTURE_SPECIAL_MOVIE_MODE_NG,
+ ErrorCode.TAKE_PICTURE_STROBO_CHARGE_NG,
+ ErrorCode.LENS_COVER_CLOSE,
+ ErrorCode.DEVICE_BUSY,
+ };
+ }
+
+ ///
+ /// Checks for an error in SDK calls and checks how to treat it
+ ///
+ /// The sender object
+ /// The return code of the SDK call
+ /// If a severe error is recognized or the
+ /// event is null with a non-severe error, it will be thrown as an exception
+ public static void CheckError(object sender, ErrorCode errorCode)
+ {
+ if (errorCode == ErrorCode.OK) return;
+ else
+ {
+ bool Severe = !NonSevereErrors.Any(t => t == errorCode);
+
+ var NonSevereErrorHappenedEvent = NonSevereErrorHappened;
+ if (!Severe) Severe = NonSevereErrorHappenedEvent == null;
+
+ if (Severe) throw new SDKException(errorCode);
+ else NonSevereErrorHappenedEvent.BeginInvoke(sender, errorCode, (a) =>
+ {
+ var ar = a as AsyncResult;
+ var invokedMethod = ar.AsyncDelegate as SDKExceptionHandler;
+ invokedMethod.EndInvoke(a);
+ }, null);
+ }
+ }
+
+ ///
+ /// Checks for an error in SDK calls and throws an exception if it's not
+ ///
+ /// The return code of the SDK call
+ /// If is something other than
+ public static void CheckError(ErrorCode errorCode)
+ {
+ if (errorCode != ErrorCode.OK) throw new SDKException(errorCode);
+ }
+
+ ///
+ /// Checks for an error in and calls
+ /// and throws an exception if it's not valid
+ ///
+ /// The return code of the SDK call
+ /// The number of references for the pointer that was used for the SDK call
+ public static int CheckError(int countOrError)
+ {
+ if (countOrError == unchecked((int)0xFFFFFFFF)) throw new SDKException(ErrorCode.INVALID_HANDLE);
+ else return countOrError;
+ }
+
+ ///
+ /// Checks for an error in and calls
+ /// and throws an exception if it's not valid
+ ///
+ /// The calling object instance. This is currently not used and is ignored.
+ /// The return code of the SDK call
+ /// The number of references for the pointer that was used for the SDK call
+ public static int CheckError(object sender, int countOrError)
+ {
+ return CheckError(countOrError);
+ }
+
+ ///
+ /// Reports an error that happened in a threading environment
+ ///
+ /// The sender object
+ /// The exception that happened
+ /// True if the error could be passed on; false otherwise
+ public static bool ReportError(object sender, Exception ex)
+ {
+ var SevereErrorHappenedEvent = SevereErrorHappened;
+ if (SevereErrorHappenedEvent == null) return false;
+ else
+ {
+ SevereErrorHappenedEvent.BeginInvoke(sender, ex, (a) =>
+ {
+ var ar = a as AsyncResult;
+ var invokedMethod = ar.AsyncDelegate as GeneralExceptionHandler;
+ invokedMethod.EndInvoke(a);
+ }, null);
+ return true;
+ }
+ }
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/IO.cs b/src/CamBooth/EDSDKLib/API/Helper/IO.cs
new file mode 100644
index 0000000..af2fa8b
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/IO.cs
@@ -0,0 +1,554 @@
+using System;
+using System.IO;
+using EOSDigital.SDK;
+using SeekOrigin = System.IO.SeekOrigin;
+using FileAccess = EOSDigital.SDK.FileAccess;
+
+namespace EOSDigital.API
+{
+ ///
+ /// Stores information to download data from the camera
+ ///
+ public class DownloadInfo
+ {
+ ///
+ /// Pointer to the downloadable object
+ ///
+ protected IntPtr inRef;
+ ///
+ /// Directory item info of the downloadable object
+ ///
+ protected DirectoryItemInfo dirInfo;
+
+ ///
+ /// Pointer to the downloadable object
+ ///
+ public IntPtr Reference { get { return inRef; } }
+ ///
+ /// The name of the file. You can change it before you pass it to the
+ /// or
+ /// method.
+ ///
+ public string FileName
+ {
+ get { return dirInfo.FileName; }
+ set { dirInfo.FileName = value; }
+ }
+ ///
+ /// The files size in bytes
+ ///
+ public int Size { get { return dirInfo.Size; } }
+ ///
+ /// The files size in bytes (as ulong)
+ ///
+ public long Size64 { get { return dirInfo.Size64; } }
+ ///
+ /// States if the file is a RAW file or not
+ ///
+ public bool IsRAW { get; protected set; }
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ /// Pointer to the downloadable object
+ internal protected DownloadInfo(IntPtr inRef)
+ {
+ if (inRef == IntPtr.Zero) throw new ArgumentNullException(nameof(inRef));
+
+ this.inRef = inRef;
+ ErrorHandler.CheckError(this, CanonSDK.GetDirectoryItemInfo(inRef, out dirInfo));
+ string ext = Path.GetExtension(FileName).ToLower();
+ if (ext == ".crw" || ext == ".cr2") IsRAW = true;
+ else IsRAW = false;
+ }
+ }
+
+ ///
+ /// Stores information about a file or folder in a camera
+ ///
+ public partial class CameraFileEntry : IDisposable
+ {
+ ///
+ /// Pointer to the file entry
+ ///
+ public IntPtr Reference { get { return Ref; } }
+ ///
+ /// The name of the entry. (volume name, folder name or file name)
+ ///
+ public string Name { get; protected set; }
+ ///
+ /// States if the entry is a folder or not
+ ///
+ public bool IsFolder { get; protected set; }
+ ///
+ /// States if the entry is a volume or not
+ ///
+ public bool IsVolume { get; protected set; }
+ ///
+ /// If the entry is a volume or folder, these are the subentries it contains. It's null if no subentries are present.
+ ///
+ public CameraFileEntry[] Entries { get; internal protected set; }
+
+ ///
+ /// Pointer to the file entry
+ ///
+ protected IntPtr Ref;
+ ///
+ /// States if the entry is disposed or not
+ ///
+ internal protected bool IsDisposed;
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal protected CameraFileEntry(IntPtr Ref, string Name, bool IsFolder, bool IsVolume)
+ {
+ this.Ref = Ref;
+ this.Name = Name;
+ this.IsFolder = IsFolder;
+ this.IsVolume = IsVolume;
+ }
+
+ ///
+ /// Destructor
+ ///
+ ~CameraFileEntry()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Releases this entry but not the subentries
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases this entry and all the subentries
+ ///
+ public void DisposeAll()
+ {
+ Dispose();
+ if (Entries != null) for (int i = 0; i < Entries.Length; i++) Entries[i].DisposeAll();
+ }
+
+ ///
+ /// Releases this entry but not the subentries
+ ///
+ /// True if called from Dispose, false if called from the finalizer/destructor
+ protected virtual void Dispose(bool managed)
+ {
+ if (!IsDisposed)
+ {
+ if (managed) DisposeThumb();
+ if (Reference != IntPtr.Zero) CanonSDK.EdsRelease(Reference);
+ IsDisposed = true;
+ }
+ }
+
+ ///
+ /// Dispose the thumbnail in an extension
+ ///
+ partial void DisposeThumb();
+
+ ///
+ /// Set the thumbnail from a stream. The thumbnail depends on the image class you want to use.
+ ///
+ /// The image stream
+ internal protected virtual void SetThumb(IntPtr stream)
+ {
+ SetThumbSub(stream);
+ }
+
+ ///
+ /// Sets the thumbnail
+ ///
+ /// The image stream
+ partial void SetThumbSub(IntPtr stream);
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(CameraFileEntry x, CameraFileEntry y)
+ {
+ // If both are null, or both are same instance, return true.
+ if (object.ReferenceEquals(x, y)) return true;
+
+ // If one is null, but not both, return false.
+ if ((object)x == null || (object)y == null) return false;
+
+ return x.Reference == y.Reference;
+ }
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(CameraFileEntry x, CameraFileEntry y)
+ {
+ return !(x == y);
+ }
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ // If objects have different types, return false.
+ if (obj.GetType() != GetType()) return false;
+
+ // If both are null, or both are same instance, return true.
+ if (object.ReferenceEquals(this, obj)) return true;
+
+ CameraFileEntry cv = obj as CameraFileEntry;
+ if (cv == null) return false;
+
+ return Reference == cv.Reference;
+ }
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ return Reference.ToInt64().GetHashCode();
+ }
+ }
+
+ ///
+ /// A Stream encapsulating an unmanaged SDK Stream.
+ /// This class can be used to overcome the differences between SDK versions
+ ///
+ public class SDKStream : Stream
+ {
+ ///
+ /// Gets a value indicating whether the current stream supports reading.
+ ///
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+ ///
+ /// Gets a value indicating whether the current stream supports seeking.
+ ///
+ public override bool CanSeek
+ {
+ get { return true; }
+ }
+ ///
+ /// Gets a value indicating whether the current stream supports writing.
+ ///
+ public override bool CanWrite
+ {
+ get { return true; }
+ }
+ ///
+ /// Gets the length in bytes of the stream.
+ ///
+ public override long Length
+ {
+ get
+ {
+ if (CanonSDK.IsVerGE34)
+ {
+ long length;
+ CanonSDK.EdsGetLength(Reference, out length);
+ return length;
+ }
+ else
+ {
+ int length;
+ CanonSDK.EdsGetLength(Reference, out length);
+ return length;
+ }
+ }
+ }
+ ///
+ /// Gets or sets the position within the current stream.
+ ///
+ public override long Position
+ {
+ get
+ {
+ if (CanonSDK.IsVerGE34)
+ {
+ long position;
+ CanonSDK.EdsGetPosition(Reference, out position);
+ return position;
+ }
+ else
+ {
+ int position;
+ CanonSDK.EdsGetPosition(Reference, out position);
+ return position;
+ }
+ }
+ set { Seek(value, SeekOrigin.Begin); }
+ }
+ ///
+ /// Pointer to the underlying SDK stream
+ ///
+ public IntPtr Reference
+ {
+ get { return _Reference; }
+ protected set { _Reference = value; }
+ }
+ private IntPtr _Reference;
+
+
+ ///
+ /// Creates a new instance of the class from an existing SDK stream
+ ///
+ /// Pointer to the SDK stream
+ public SDKStream(IntPtr sdkStream)
+ {
+ if (sdkStream == IntPtr.Zero) throw new ArgumentNullException(nameof(sdkStream));
+ Reference = sdkStream;
+ }
+
+ ///
+ /// Creates a new instance of the class with an underlying SDK file stream
+ ///
+ /// Path to the file
+ /// State how to create the stream
+ /// File access type
+ public SDKStream(string filepath, FileCreateDisposition createDisposition, FileAccess access)
+ {
+ if (filepath == null) throw new ArgumentNullException(nameof(filepath));
+ ErrorHandler.CheckError(CanonSDK.EdsCreateFileStreamEx(filepath, createDisposition, access, out _Reference));
+ }
+
+ ///
+ /// Creates a new instance of the class with an underlying SDK memory stream.
+ /// This stream will resize itself if the current length is exceeded
+ ///
+ /// Initial buffer size of the stream in bytes
+ public SDKStream(long length)
+ {
+ ErrorCode err;
+ if (CanonSDK.IsVerGE34) err = CanonSDK.EdsCreateMemoryStream(length, out _Reference);
+ else err = CanonSDK.EdsCreateMemoryStream((int)length, out _Reference);
+ ErrorHandler.CheckError(err);
+ }
+
+ ///
+ /// Creates a new instance of the class with an underlying SDK memory stream.
+ /// Note that this stream will not resize itself
+ ///
+ /// The memory buffer to use for the stream
+ public SDKStream(byte[] buffer)
+ {
+ if (buffer == null) throw new ArgumentNullException(nameof(buffer));
+
+ ErrorCode err;
+ if (CanonSDK.IsVerGE34) err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, buffer.LongLength, out _Reference);
+ else err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)buffer.LongLength, out _Reference);
+ ErrorHandler.CheckError(err);
+ }
+
+ ///
+ /// Creates a new instance of the class with an underlying SDK memory stream.
+ /// Note that this stream will not resize itself
+ ///
+ /// Pointer to the memory buffer to use for the stream
+ /// The size of the memory buffer in bytes
+ public SDKStream(IntPtr buffer, long length)
+ {
+ if (buffer == IntPtr.Zero) throw new ArgumentNullException(nameof(buffer));
+
+ ErrorCode err;
+ if (CanonSDK.IsVerGE34) err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, length, out _Reference);
+ else err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)length, out _Reference);
+ ErrorHandler.CheckError(err);
+ }
+
+ ///
+ /// Creates a new instance of the class from an existing SDK stream.
+ /// Note that this calls internally and ignores all parameters but
+ ///
+ /// Pointer to the underlying SDK buffer. Ignored parameter
+ /// Pointer to the SDK stream
+ /// The size of the underlying SDK buffer in bytes. Ignored parameter
+ [Obsolete("Not necessary anymore. Buffer and length is not used.")]
+ public SDKStream(IntPtr buffer, IntPtr sdkStream, long length)
+ : this(sdkStream)
+ { }
+
+
+ ///
+ /// Clears all buffers for this stream and causes any buffered data to be
+ /// written to the underlying device.
+ /// This is not applicable to the SDK and therefore does nothing.
+ ///
+ public override void Flush()
+ {
+ //Nothing to do here
+ }
+
+ ///
+ /// 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 (int)Read(buffer, offset, count);
+ }
+
+ ///
+ /// 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 unsafe long Read(byte[] buffer, long offset, long count)
+ {
+ if (buffer.LongLength < offset + count) throw new ArgumentOutOfRangeException();
+
+ fixed (byte* bufferPtr = buffer)
+ {
+ byte* offsetBufferPtr = bufferPtr + offset;
+
+ if (CanonSDK.IsVerGE34)
+ {
+ long read;
+ ErrorHandler.CheckError(CanonSDK.EdsRead(_Reference, count, (IntPtr)offsetBufferPtr, out read));
+ return read;
+ }
+ else
+ {
+ int read;
+ ErrorHandler.CheckError(CanonSDK.EdsRead(_Reference, (int)count, (IntPtr)offsetBufferPtr, out read));
+ return read;
+ }
+ }
+ }
+
+ ///
+ /// Sets the position within the current stream.
+ ///
+ /// A byte offset relative to the origin parameter.
+ /// A value of type indicating the
+ /// reference point used to obtain the new position.
+ /// The new position within the current stream.
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ SDK.SeekOrigin sdkOrigin;
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ sdkOrigin = SDK.SeekOrigin.Begin;
+ break;
+ case SeekOrigin.Current:
+ sdkOrigin = SDK.SeekOrigin.Current;
+ break;
+ case SeekOrigin.End:
+ sdkOrigin = SDK.SeekOrigin.End;
+ break;
+
+ default:
+ throw new ArgumentException("Not a valid enum value", nameof(origin));
+ }
+
+ if (CanonSDK.IsVerGE34) ErrorHandler.CheckError(CanonSDK.EdsSeek(_Reference, offset, sdkOrigin));
+ else ErrorHandler.CheckError(CanonSDK.EdsSeek(_Reference, (int)offset, sdkOrigin));
+
+ return Position;
+ }
+
+ ///
+ /// Always throws a
+ ///
+ /// The desired length of the current stream in bytes.
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// 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)
+ {
+ Write(buffer, (long)offset, count);
+ }
+
+ ///
+ /// 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 unsafe void Write(byte[] buffer, long offset, long count)
+ {
+ if (buffer.LongLength < offset + count) throw new ArgumentOutOfRangeException();
+
+ fixed (byte* bufferPtr = buffer)
+ {
+ byte* offsetBufferPtr = bufferPtr + offset;
+
+ if (CanonSDK.IsVerGE34)
+ {
+ long written;
+ ErrorHandler.CheckError(CanonSDK.EdsWrite(_Reference, count, (IntPtr)offsetBufferPtr, out written));
+ }
+ else
+ {
+ int written;
+ ErrorHandler.CheckError(CanonSDK.EdsWrite(_Reference, (int)count, (IntPtr)offsetBufferPtr, out written));
+ }
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the and optionally
+ /// releases the managed resources.
+ ///
+ /// true to release both managed and unmanaged resources;
+ /// false to release only unmanaged
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (_Reference != IntPtr.Zero)
+ {
+ int err = CanonSDK.EdsRelease(_Reference);
+ Reference = IntPtr.Zero;
+ if (disposing) ErrorHandler.CheckError(err);
+ }
+ }
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/STAThread.cs b/src/CamBooth/EDSDKLib/API/Helper/STAThread.cs
new file mode 100644
index 0000000..7c4a033
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/STAThread.cs
@@ -0,0 +1,324 @@
+using System;
+using System.Threading;
+
+namespace EOSDigital.API
+{
+ ///
+ /// This static class executes things on an STA thread and provides a method to create an STA thread
+ ///
+ public class STAThread
+ {
+ #region Variables
+
+ ///
+ /// Object that is used for the lock keyword to ensure only one SDK command is executed at a time
+ ///
+ public static readonly object ExecLock = new object();
+ ///
+ /// States if the calling thread is in a Single Threaded Apartment or not
+ ///
+ public static bool IsSTAThread
+ {
+ get { return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA; }
+ }
+
+ ///
+ /// States if this thread is currently running
+ ///
+ public bool IsRunning
+ {
+ get { return isRunning; }
+ }
+ ///
+ /// ID of the associated thread
+ ///
+ public int ThreadID
+ {
+ get { return mainThread.ManagedThreadId; }
+ }
+
+ ///
+ /// The main thread where everything will be executed on
+ ///
+ private Thread mainThread;
+ ///
+ /// States if the execution thread is currently running
+ ///
+ private bool isRunning = false;
+
+ ///
+ /// Lock object to make sure only one command at a time is executed
+ ///
+ private object runLock = new object();
+ ///
+ /// Lock object to ensure that an action executed on the thread does not invoke on itself
+ ///
+ private object cmdLock = new object();
+ ///
+ /// Lock object to synchronize between execution and calling thread
+ ///
+ protected object threadLock1 = new object();
+ ///
+ /// Lock object to synchronize between execution and calling thread
+ ///
+ private object threadLock2 = new object();
+ ///
+ /// States if the first lock is currently blocking or not
+ ///
+ protected bool block1 = true;
+ ///
+ /// States if the second lock is currently blocking or not
+ ///
+ private bool block2 = true;
+
+ ///
+ /// The action to be executed
+ ///
+ private Action runAction;
+ ///
+ /// Storage for an exception that might have happened on the execution thread
+ ///
+ private Exception runException;
+
+ #endregion
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ internal STAThread()
+ { }
+
+ #region Public Methods
+
+ ///
+ /// Starts the execution loop
+ ///
+ public void Start()
+ {
+ lock (runLock)
+ {
+ if (!isRunning)
+ {
+ mainThread = CreateThread(ExecutionLoop);
+ isRunning = true;
+ mainThread.Start();
+ WaitForThread();
+ }
+ }
+ }
+
+ ///
+ /// Shuts down the execution loop and waits for it to finish
+ ///
+ public void Shutdown()
+ {
+ lock (runLock)
+ {
+ if (isRunning)
+ {
+ isRunning = false;
+ NotifyThread();
+ mainThread.Join();
+ }
+ }
+ }
+
+ ///
+ /// Executes an action on this STA thread
+ ///
+ /// The action to execute
+ /// will be thrown if action is null
+ /// if an exception is thrown on the thread,
+ /// it will be rethrown as inner exception of this exception
+ public void Invoke(Action action)
+ {
+ if (action == null) throw new ArgumentNullException(nameof(action));
+
+ //If the method is called from the execution thread, directly execute it.
+ //This prevents possible deadlocks when trying to acquire the runLock while waiting within for the thread to finish.
+ if (Monitor.TryEnter(cmdLock))
+ {
+ try { action(); }
+ finally { Monitor.Exit(cmdLock); }
+ }
+ else
+ {
+ lock (runLock)
+ {
+ if (!isRunning) throw new InvalidOperationException("Thread is not running");
+
+ runAction = action;
+ NotifyThread();
+ WaitForThread();
+ if (runException != null) throw new ExecutionException(runException.Message, runException);
+ }
+ }
+ }
+
+ ///
+ /// Executes a function on this STA thread
+ ///
+ /// The function to execute
+ /// the return value of the function
+ /// will be thrown if func is null
+ /// if an exception is thrown on the thread,
+ /// it will be rethrown as inner exception of this exception
+ public T Invoke(Func func)
+ {
+ if (func == null) throw new ArgumentNullException(nameof(func));
+
+ T result = default(T);
+ Invoke(delegate { result = func(); });
+ return result;
+ }
+
+ #endregion
+
+ #region Static Methods
+
+ ///
+ /// Creates a thread in a Single Threaded Apartment
+ ///
+ /// The command to run on this thread
+ /// An STA thread
+ public static Thread CreateThread(Action action)
+ {
+ var thread = new Thread(new ThreadStart(action));
+ thread.SetApartmentState(ApartmentState.STA);
+ return thread;
+ }
+
+ ///
+ /// Executes an action on a newly created STA Thread
+ /// and optionally waits for it to finish executing
+ ///
+ /// The action to execute
+ /// If true, the action is executed synchronously or if false, asynchronously.
+ public static void ExecuteThread(Action action, bool wait)
+ {
+ Exception runException = null;
+ Thread thread = CreateThread(delegate
+ {
+ try { action(); }
+ catch (Exception ex)
+ {
+ if (wait) runException = ex;
+ else throw;
+ }
+ });
+
+ thread.Start();
+
+ if (wait)
+ {
+ thread.Join();
+ if (runException != null) throw new ExecutionException(runException.Message, runException);
+ }
+ }
+
+ ///
+ /// Executes a function on a newly created STA Thread
+ ///
+ /// The function to execute
+ /// The return value of the given function
+ public static T ExecuteThread(Func func)
+ {
+ Exception runException = null;
+ T result = default(T);
+ Thread thread = CreateThread(delegate
+ {
+ try { result = func(); }
+ catch (Exception ex) { runException = ex; }
+ });
+ thread.Start();
+ thread.Join();
+ if (runException != null) throw new ExecutionException(runException.Message, runException);
+ return result;
+ }
+
+ #endregion
+
+ #region Subroutines
+
+ ///
+ /// Notifies the execution loop to execute something
+ ///
+ private void NotifyThread()
+ {
+ lock (threadLock1)
+ {
+ block1 = false;
+ Monitor.Pulse(threadLock1);
+ }
+ }
+
+ ///
+ /// Blocks until the execution loop is done with the work
+ ///
+ private void WaitForThread()
+ {
+ lock (threadLock2)
+ {
+ while (block2) Monitor.Wait(threadLock2);
+ block2 = true;
+ }
+ }
+
+ ///
+ /// Releases the waiting method to continue
+ ///
+ private void ReleaseWait()
+ {
+ lock (threadLock2)
+ {
+ block2 = false;
+ Monitor.Pulse(threadLock2);
+ }
+ }
+
+ ///
+ /// The waiting routine on the execution loop
+ ///
+ protected virtual void WaitForNotification()
+ {
+ lock (threadLock1)
+ {
+ while (block1 && isRunning) { Monitor.Wait(threadLock1); }
+ block1 = true;
+ }
+ }
+
+ ///
+ /// The loop that is executed on the thread and where the work is done
+ ///
+ private void ExecutionLoop()
+ {
+ ReleaseWait();
+
+ try
+ {
+ lock (cmdLock)
+ {
+ while (isRunning)
+ {
+ WaitForNotification();
+ if (!isRunning) return;
+
+ runException = null;
+ try { lock (ExecLock) { runAction(); } }
+ catch (Exception ex) { runException = ex; }
+
+ ReleaseWait();
+ }
+ }
+ }
+ finally
+ {
+ isRunning = false;
+ ReleaseWait();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/API/Helper/ValueCollections.cs b/src/CamBooth/EDSDKLib/API/Helper/ValueCollections.cs
new file mode 100644
index 0000000..cd917e1
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/API/Helper/ValueCollections.cs
@@ -0,0 +1,788 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using EOSDigital.SDK;
+
+namespace EOSDigital.API
+{
+ ///
+ /// Stores CameraValues and provides methods to get those values. Abstract class.
+ ///
+ public abstract class ValueBase
+ {
+ ///
+ /// Get the value from an int out of given possible values.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// Possible values that will be searched for the given value
+ /// The CameraValue with given uint representation
+ /// No for the given value
+ public static CameraValue GetValue(int value, List Values)
+ {
+ var arr = Values.Where(t => t.IntValue == value).ToArray();
+ if (arr.Length == 0)
+ {
+ var invalid = Values.FirstOrDefault(t => t.IntValue == unchecked((int)0xFFFFFFFF));
+ if (invalid != null) return invalid;
+ else throw new KeyNotFoundException("There is no CameraValue for this ID");
+ }
+ else { return arr[0]; }
+ }
+
+ ///
+ /// Get the value from a string out of given possible values.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// Possible values that will be searched for the given value
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value, List Values)
+ {
+ var arr = Values.Where(t => t.StringValue == value).ToArray();
+ if (arr.Length == 0)
+ {
+ var invalid = Values.FirstOrDefault(t => t.IntValue == unchecked((int)0xFFFFFFFF));
+ if (invalid != null) return invalid;
+ else throw new KeyNotFoundException("There is no CameraValue for this ID");
+ }
+ else { return arr[0]; }
+ }
+
+ ///
+ /// Get the value from a double out of given possible values.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// Possible values that will be searched for the given value
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value, List Values)
+ {
+ CameraValue[] sorted = Values.Distinct(new CameraValueComparer())
+ .Where(t => t.IntValue != unchecked((int)0xFFFFFFFF) && t != TvValues.Bulb && t != ISOValues.Auto)
+ .OrderBy(t => t.DoubleValue).ToArray();
+
+ for (int i = 0; i < sorted.Length; i++)
+ {
+ //Exact match:
+ if (Math.Abs(sorted[i].DoubleValue - value) <= 0.00000000001) return sorted[i];
+ else if (sorted[i].DoubleValue > value)
+ {
+ //Value is smaller than the range of given list. Return first:
+ if (i == 0) return sorted[i];
+ else
+ {
+ //Select CameraValue closest to given value
+ double delta1 = value - sorted[i - 1].DoubleValue;
+ double delta = sorted[i].DoubleValue - value;
+ if (delta > delta1) return sorted[i - 1];
+ else return sorted[i];
+ }
+ }
+ }
+
+ //Value is bigger than the range of given list. Return last:
+ return sorted[sorted.Length - 1];
+ }
+
+ ///
+ /// Comparer for s
+ ///
+ protected sealed class CameraValueComparer : IEqualityComparer
+ {
+ ///
+ /// Determines whether the specified s are equal.
+ ///
+ /// The first
+ /// The second
+ /// true if the specified s are equal; otherwise, false.
+ public bool Equals(CameraValue x, CameraValue y)
+ {
+ return x.Equals(y);
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public int GetHashCode(CameraValue obj)
+ {
+ return obj.GetHashCode();
+ }
+ }
+ }
+
+ ///
+ /// Stores Av Values and provides methods to get those values
+ ///
+ public sealed class AvValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+ ///
+ /// The Av of the "Auto" or "None" setting
+ ///
+ public static readonly CameraValue Auto = new CameraValue("Auto", 0x00000000, 0, PropertyID.Av);
+ ///
+ /// The Av of an invalid setting
+ ///
+ public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.Av);
+
+ static AvValues()
+ {
+ values = new List()
+ {
+ Auto,
+ new CameraValue("1", 0x08, 1, PropertyID.Av),
+ new CameraValue("1.1", 0x0B, 1.1, PropertyID.Av),
+ new CameraValue("1.2", 0x0C, 1.2, PropertyID.Av),
+ new CameraValue("1.2 (1/3)", 0x0D, 1.2, PropertyID.Av),
+ new CameraValue("1.4", 0x10, 1.4, PropertyID.Av),
+ new CameraValue("1.6", 0x13, 1.6, PropertyID.Av),
+ new CameraValue("1.8", 0x14, 1.8, PropertyID.Av),
+ new CameraValue("1.8 (1/3)", 0x15, 1.8, PropertyID.Av),
+ new CameraValue("2", 0x18, 2, PropertyID.Av),
+ new CameraValue("2.2", 0x1B, 2.2, PropertyID.Av),
+ new CameraValue("2.5", 0x1C, 2.5, PropertyID.Av),
+ new CameraValue("2.5 (1/3)", 0x1D, 2.5, PropertyID.Av),
+ new CameraValue("2.8", 0x20, 2.8, PropertyID.Av),
+ new CameraValue("3.2", 0x23, 3.2, PropertyID.Av),
+ new CameraValue("3.5", 0x24, 3.5, PropertyID.Av),
+ new CameraValue("3.5 (1/3)", 0x25, 3.5, PropertyID.Av),
+ new CameraValue("4", 0x28, 4, PropertyID.Av),
+ new CameraValue("4.5", 0x2B, 4.5, PropertyID.Av),
+ new CameraValue("4.5 (1/3)", 0x2C, 4.5, PropertyID.Av),
+ new CameraValue("5.0", 0x2D, 5.0, PropertyID.Av),
+ new CameraValue("5.6", 0x30, 5.6, PropertyID.Av),
+ new CameraValue("6.3", 0x33, 6.3, PropertyID.Av),
+ new CameraValue("6.7", 0x34, 6.7, PropertyID.Av),
+ new CameraValue("7.1", 0x35, 7.1, PropertyID.Av),
+ new CameraValue("8", 0x38, 8, PropertyID.Av),
+ new CameraValue("9", 0x3B, 9, PropertyID.Av),
+ new CameraValue("9.5", 0x3C, 9.5, PropertyID.Av),
+ new CameraValue("10", 0x3D, 10, PropertyID.Av),
+ new CameraValue("11", 0x40, 11, PropertyID.Av),
+ new CameraValue("13 (1/3)", 0x43, 13, PropertyID.Av),
+ new CameraValue("13", 0x44, 13, PropertyID.Av),
+ new CameraValue("14", 0x45, 14, PropertyID.Av),
+ new CameraValue("16", 0x48, 16, PropertyID.Av),
+ new CameraValue("18", 0x4B, 18, PropertyID.Av),
+ new CameraValue("19", 0x4C, 19, PropertyID.Av),
+ new CameraValue("20", 0x4D, 20, PropertyID.Av),
+ new CameraValue("22", 0x50, 22, PropertyID.Av),
+ new CameraValue("25", 0x53, 25, PropertyID.Av),
+ new CameraValue("27", 0x54, 27, PropertyID.Av),
+ new CameraValue("29", 0x55, 29, PropertyID.Av),
+ new CameraValue("32", 0x58, 32, PropertyID.Av),
+ new CameraValue("36", 0x5B, 36, PropertyID.Av),
+ new CameraValue("38", 0x5C, 38, PropertyID.Av),
+ new CameraValue("40", 0x5D, 40, PropertyID.Av),
+ new CameraValue("45", 0x60, 45, PropertyID.Av),
+ new CameraValue("51", 0x63, 51, PropertyID.Av),
+ new CameraValue("54", 0x64, 54, PropertyID.Av),
+ new CameraValue("57", 0x65, 57, PropertyID.Av),
+ new CameraValue("64", 0x68, 64, PropertyID.Av),
+ new CameraValue("72", 0x6B, 72, PropertyID.Av),
+ new CameraValue("76", 0x6C, 76, PropertyID.Av),
+ new CameraValue("80", 0x6D, 80, PropertyID.Av),
+ new CameraValue("91", 0x70, 91, PropertyID.Av),
+ Invalid
+ };
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+
+ ///
+ /// Stores Tv Values and provides methods to get those values
+ ///
+ public sealed class TvValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+ ///
+ /// The Tv of the "Auto" setting
+ ///
+ public static readonly CameraValue Auto = new CameraValue("Auto", 0x00000000, 0, PropertyID.Tv);
+ ///
+ /// The Tv of the "Bulb" setting
+ ///
+ public static readonly CameraValue Bulb = new CameraValue("Bulb", 0x0C, 0, PropertyID.Tv);
+ ///
+ /// The Tv of an invalid setting
+ ///
+ public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.Tv);
+
+ static TvValues()
+ {
+ values = new List()
+ {
+ Auto,
+ Bulb,
+ new CameraValue("30\"", 0x10, 30, PropertyID.Tv),
+ new CameraValue("25\"", 0x13, 25, PropertyID.Tv),
+ new CameraValue("20\"", 0x14, 20, PropertyID.Tv),
+ new CameraValue("20\" (1/3)", 0x15, 20, PropertyID.Tv),
+ new CameraValue("15\"", 0x18, 15, PropertyID.Tv),
+ new CameraValue("13\"", 0x1B, 13, PropertyID.Tv),
+ new CameraValue("10\"", 0x1C, 10, PropertyID.Tv),
+ new CameraValue("10\" (1/3)", 0x1D, 10, PropertyID.Tv),
+ new CameraValue("8\"", 0x20, 8, PropertyID.Tv),
+ new CameraValue("6\" (1/3)", 0x23, 6, PropertyID.Tv),
+ new CameraValue("6\"", 0x24, 6, PropertyID.Tv),
+ new CameraValue("5\"", 0x25, 5, PropertyID.Tv),
+ new CameraValue("4\"", 0x28, 4, PropertyID.Tv),
+ new CameraValue("3\"2", 0x2B, 3.2, PropertyID.Tv),
+ new CameraValue("3\"", 0x2C, 3, PropertyID.Tv),
+ new CameraValue("2\"5", 0x2D, 2.5, PropertyID.Tv),
+ new CameraValue("2\"", 0x30, 2, PropertyID.Tv),
+ new CameraValue("1\"6", 0x33, 1.6, PropertyID.Tv),
+ new CameraValue("1\"5", 0x34, 1.5, PropertyID.Tv),
+ new CameraValue("1\"3", 0x35, 1.3, PropertyID.Tv),
+ new CameraValue("1\"", 0x38, 1, PropertyID.Tv),
+ new CameraValue("0\"8", 0x3B, 0.8, PropertyID.Tv),
+ new CameraValue("0\"7", 0x3C, 0.7, PropertyID.Tv),
+ new CameraValue("0\"6", 0x3D, 0.6, PropertyID.Tv),
+ new CameraValue("0\"5", 0x40, 0.5, PropertyID.Tv),
+ new CameraValue("0\"4", 0x43, 0.4, PropertyID.Tv),
+ new CameraValue("0\"3", 0x44, 0.3, PropertyID.Tv),
+ new CameraValue("0\"3 (1/3)", 0x45, 0.3, PropertyID.Tv),
+ new CameraValue("1/4", 0x48, 1 / 4d, PropertyID.Tv),
+ new CameraValue("1/5", 0x4B, 1 / 5d, PropertyID.Tv),
+ new CameraValue("1/6", 0x4C, 1 / 6d, PropertyID.Tv),
+ new CameraValue("1/6 (1/3)", 0x4D, 1 / 6d, PropertyID.Tv),
+ new CameraValue("1/8", 0x50, 1 / 8d, PropertyID.Tv),
+ new CameraValue("1/10 (1/3)", 0x53, 1 / 10d, PropertyID.Tv),
+ new CameraValue("1/10", 0x54, 1 / 10d, PropertyID.Tv),
+ new CameraValue("1/13", 0x55, 1 / 13d, PropertyID.Tv),
+ new CameraValue("1/15", 0x58, 1 / 15d, PropertyID.Tv),
+ new CameraValue("1/20 (1/3)", 0x5B, 1 / 20d, PropertyID.Tv),
+ new CameraValue("1/20", 0x5C, 1 / 20d, PropertyID.Tv),
+ new CameraValue("1/25", 0x5D, 1 / 25d, PropertyID.Tv),
+ new CameraValue("1/30", 0x60, 1 / 30d, PropertyID.Tv),
+ new CameraValue("1/40", 0x63, 1 / 40d, PropertyID.Tv),
+ new CameraValue("1/45", 0x64, 1 / 45d, PropertyID.Tv),
+ new CameraValue("1/50", 0x65, 1 / 50d, PropertyID.Tv),
+ new CameraValue("1/60", 0x68, 1 / 60d, PropertyID.Tv),
+ new CameraValue("1/80", 0x6B, 1 / 80d, PropertyID.Tv),
+ new CameraValue("1/90", 0x6C, 1 / 90d, PropertyID.Tv),
+ new CameraValue("1/100", 0x6D, 1 / 100d, PropertyID.Tv),
+ new CameraValue("1/125", 0x70, 1 / 125d, PropertyID.Tv),
+ new CameraValue("1/160", 0x73, 1 / 160d, PropertyID.Tv),
+ new CameraValue("1/180", 0x74, 1 / 180d, PropertyID.Tv),
+ new CameraValue("1/200", 0x75, 1 / 200d, PropertyID.Tv),
+ new CameraValue("1/250", 0x78, 1 / 150d, PropertyID.Tv),
+ new CameraValue("1/320", 0x7B, 1 / 320d, PropertyID.Tv),
+ new CameraValue("1/350", 0x7C, 1 / 350d, PropertyID.Tv),
+ new CameraValue("1/400", 0x7D, 1 / 400d, PropertyID.Tv),
+ new CameraValue("1/500", 0x80, 1 / 500d, PropertyID.Tv),
+ new CameraValue("1/640", 0x83, 1 / 640d, PropertyID.Tv),
+ new CameraValue("1/750", 0x84, 1 / 750d, PropertyID.Tv),
+ new CameraValue("1/800", 0x85, 1 / 800d, PropertyID.Tv),
+ new CameraValue("1/1000", 0x88, 1 / 1000d, PropertyID.Tv),
+ new CameraValue("1/1250", 0x8B, 1 / 1250d, PropertyID.Tv),
+ new CameraValue("1/1500", 0x8C, 1 / 1500d, PropertyID.Tv),
+ new CameraValue("1/1600", 0x8D, 1 / 1600d, PropertyID.Tv),
+ new CameraValue("1/2000", 0x90, 1 / 2000d, PropertyID.Tv),
+ new CameraValue("1/2500", 0x93, 1 / 2500d, PropertyID.Tv),
+ new CameraValue("1/3000", 0x94, 1 / 3000d, PropertyID.Tv),
+ new CameraValue("1/3200", 0x95, 1 / 3200d, PropertyID.Tv),
+ new CameraValue("1/4000", 0x98, 1 / 4000d, PropertyID.Tv),
+ new CameraValue("1/5000", 0x9B, 1 / 5000d, PropertyID.Tv),
+ new CameraValue("1/6000", 0x9C, 1 / 6000d, PropertyID.Tv),
+ new CameraValue("1/6400", 0x9D, 1 / 6400d, PropertyID.Tv),
+ new CameraValue("1/8000", 0xA0, 1 / 8000d, PropertyID.Tv),
+ Invalid
+ };
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+
+ ///
+ /// Stores ISO Values and provides methods to get those values
+ ///
+ public sealed class ISOValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+ ///
+ /// The ISO of the "Auto" setting
+ ///
+ public static readonly CameraValue Auto = new CameraValue("ISO Auto", 0x00000000, 0, PropertyID.ISO);
+ ///
+ /// The ISO of an invalid setting
+ ///
+ public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.ISO);
+
+ static ISOValues()
+ {
+ values = new List()
+ {
+ Auto,
+ new CameraValue("ISO 50", 0x00000040, 50, PropertyID.ISO),
+ new CameraValue("ISO 100", 0x00000048, 100, PropertyID.ISO),
+ new CameraValue("ISO 125", 0x0000004b, 125, PropertyID.ISO),
+ new CameraValue("ISO 160", 0x0000004d, 160, PropertyID.ISO),
+ new CameraValue("ISO 200", 0x00000050, 200, PropertyID.ISO),
+ new CameraValue("ISO 250", 0x00000053, 250, PropertyID.ISO),
+ new CameraValue("ISO 320", 0x00000055, 320, PropertyID.ISO),
+ new CameraValue("ISO 400", 0x00000058, 400, PropertyID.ISO),
+ new CameraValue("ISO 500", 0x0000005b, 500, PropertyID.ISO),
+ new CameraValue("ISO 640", 0x0000005d, 640, PropertyID.ISO),
+ new CameraValue("ISO 800", 0x00000060, 800, PropertyID.ISO),
+ new CameraValue("ISO 1000", 0x00000063, 1000, PropertyID.ISO),
+ new CameraValue("ISO 1250", 0x00000065, 1250, PropertyID.ISO),
+ new CameraValue("ISO 1600", 0x00000068, 1600, PropertyID.ISO),
+ new CameraValue("ISO 2000", 0x0000006b, 2000, PropertyID.ISO),
+ new CameraValue("ISO 2500", 0x0000006d, 2500, PropertyID.ISO),
+ new CameraValue("ISO 3200", 0x00000070, 3200, PropertyID.ISO),
+ new CameraValue("ISO 4000", 0x00000073, 4000, PropertyID.ISO),
+ new CameraValue("ISO 5000", 0x00000075, 5000, PropertyID.ISO),
+ new CameraValue("ISO 6400", 0x00000078, 6400, PropertyID.ISO),
+ new CameraValue("ISO 8000", 0x0000007b, 8000, PropertyID.ISO),
+ new CameraValue("ISO 10000", 0x0000007d, 10000, PropertyID.ISO),
+ new CameraValue("ISO 12800", 0x00000080, 12800, PropertyID.ISO),
+ new CameraValue("ISO 16000", 0x00000083, 16000, PropertyID.ISO),
+ new CameraValue("ISO 20000", 0x00000085, 20000, PropertyID.ISO),
+ new CameraValue("ISO 25600", 0x00000088, 25600, PropertyID.ISO),
+ new CameraValue("ISO 51200", 0x00000090, 51200, PropertyID.ISO),
+ new CameraValue("ISO 102400", 0x00000098, 102400, PropertyID.ISO),
+ Invalid
+ };
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+
+ ///
+ /// Stores Exposure Compensation Values and provides methods to get those values
+ ///
+ public sealed class ExpCompValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+ ///
+ /// The ExposureCompensation of Zero
+ ///
+ public static readonly CameraValue Zero = new CameraValue("0", 0x00, 0, PropertyID.ExposureCompensation);
+ ///
+ /// The ExposureCompensation of an invalid setting
+ ///
+ public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.ExposureCompensation);
+
+ static ExpCompValues()
+ {
+ values = new List()
+ {
+ new CameraValue("+5", 0x28, 5, PropertyID.ExposureCompensation),
+ new CameraValue("+4 2/3", 0x25, 4 + (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+4 1/2", 0x24, 4 + (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("+4 1/3", 0x23, 4 + (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+4", 0x20, 4, PropertyID.ExposureCompensation),
+ new CameraValue("+3 2/3", 0x1D, 3 + (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+3 1/2", 0x1C, 3 + (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("+3 1/3", 0x1B, 3 + (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+3", 0x18, 3, PropertyID.ExposureCompensation),
+ new CameraValue("+2 2/3", 0x15, 2 + (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+2 1/2", 0x14, 2 + (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("+2 1/3", 0x13, 2 + (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+2", 0x10, 2, PropertyID.ExposureCompensation),
+ new CameraValue("+1 2/3", 0x0D, 1 + (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+1 1/2", 0x0C, 1 + (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("+1 1/3", 0x0B, 1 + (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("+1", 0x08, 1, PropertyID.ExposureCompensation),
+ new CameraValue("+2/3", 0x05, 2 / 3d, PropertyID.ExposureCompensation),
+ new CameraValue("+1/2", 0x04, 1 / 2d, PropertyID.ExposureCompensation),
+ new CameraValue("+1/3", 0x03, 1 / 3d, PropertyID.ExposureCompensation),
+ Zero,
+ new CameraValue("–1/3", 0xFD, -1 / 3d, PropertyID.ExposureCompensation),
+ new CameraValue("–1/2", 0xFC, -1 / 2d, PropertyID.ExposureCompensation),
+ new CameraValue("–2/3", 0xFB, -2 / 3d, PropertyID.ExposureCompensation),
+ new CameraValue("–1", 0xF8, -1, PropertyID.ExposureCompensation),
+ new CameraValue("–1 1/3", 0xF5, -1 - (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("–1 1/2", 0xF4, -1 - (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("–1 2/3", 0xF3, -1 - (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("–2", 0xF0, -2, PropertyID.ExposureCompensation),
+ new CameraValue("–2 1/3", 0xED, -2 - (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("–2 1/2", 0xEC, -2 - (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("–2 2/3", 0xEB, -2 - (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("–3", 0xE8, -3, PropertyID.ExposureCompensation),
+ new CameraValue("-3 1/3", 0xE5, -3 - (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("-3 1/2", 0xE4, -3 - (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("-3 2/3", 0xE3, -3 - (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("-4", 0xE0, -4, PropertyID.ExposureCompensation),
+ new CameraValue("-4 1/3", 0xDD, -4 - (1 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("-4 1/2", 0xDC, -4 - (1 / 2d), PropertyID.ExposureCompensation),
+ new CameraValue("-4 2/3", 0xDB, -4 - (2 / 3d), PropertyID.ExposureCompensation),
+ new CameraValue("-5", 0xD8, -5, PropertyID.ExposureCompensation),
+ Invalid
+ };
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+
+ ///
+ /// Stores AE Mode Values and provides methods to get those values
+ ///
+ public sealed class AEModeValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+#pragma warning disable 1591
+
+ public static readonly CameraValue Program = new CameraValue("Program", 0, 0, PropertyID.AEMode);
+ public static readonly CameraValue Tv = new CameraValue("Tv", 1, 0, PropertyID.AEMode);
+ public static readonly CameraValue Av = new CameraValue("Av", 2, 0, PropertyID.AEMode);
+ public static readonly CameraValue Manual = new CameraValue("Manual", 3, 0, PropertyID.AEMode);
+ public static readonly CameraValue Bulb = new CameraValue("Bulb", 4, 0, PropertyID.AEMode);
+ public static readonly CameraValue A_DEP = new CameraValue("A_DEP", 5, 0, PropertyID.AEMode);
+ public static readonly CameraValue DEP = new CameraValue("DEP", 6, 0, PropertyID.AEMode);
+ public static readonly CameraValue Custom = new CameraValue("Custom", 7, 0, PropertyID.AEMode);
+ public static readonly CameraValue Lock = new CameraValue("Lock", 8, 0, PropertyID.AEMode);
+ public static readonly CameraValue Green = new CameraValue("Green", 9, 0, PropertyID.AEMode);
+ public static readonly CameraValue NightPortrait = new CameraValue("NightPortrait", 10, 0, PropertyID.AEMode);
+ public static readonly CameraValue Sports = new CameraValue("Sports", 11, 0, PropertyID.AEMode);
+ public static readonly CameraValue Portrait = new CameraValue("Portrait", 12, 0, PropertyID.AEMode);
+ public static readonly CameraValue Landscape = new CameraValue("Landscape", 13, 0, PropertyID.AEMode);
+ public static readonly CameraValue Closeup = new CameraValue("Closeup", 14, 0, PropertyID.AEMode);
+ public static readonly CameraValue FlashOff = new CameraValue("FlashOff", 15, 0, PropertyID.AEMode);
+ public static readonly CameraValue Custom2 = new CameraValue("Custom2", 16, 0, PropertyID.AEMode);
+ public static readonly CameraValue Custom3 = new CameraValue("Custom3", 17, 0, PropertyID.AEMode);
+ public static readonly CameraValue CreativeAuto = new CameraValue("CreativeAuto", 19, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie = new CameraValue("Movie", 20, 0, PropertyID.AEMode);
+ public static readonly CameraValue PhotoInMovie = new CameraValue("PhotoInMovie", 21, 0, PropertyID.AEMode);
+ public static readonly CameraValue SceneIntelligentAuto = new CameraValue("SceneIntelligentAuto", 22, 0, PropertyID.AEMode);
+ public static readonly CameraValue Scene = new CameraValue("Scene", 25, 0, PropertyID.AEMode);
+ public static readonly CameraValue NightScenes = new CameraValue("NightScenes", 23, 0, PropertyID.AEMode);
+ public static readonly CameraValue BacklitScenes = new CameraValue("BacklitScenes", 24, 0, PropertyID.AEMode);
+ public static readonly CameraValue Children = new CameraValue("Children", 26, 0, PropertyID.AEMode);
+ public static readonly CameraValue Food = new CameraValue("Food", 27, 0, PropertyID.AEMode);
+ public static readonly CameraValue CandlelightPortraits = new CameraValue("CandlelightPortraits", 28, 0, PropertyID.AEMode);
+ public static readonly CameraValue CreativeFilter = new CameraValue("CreativeFilter", 29, 0, PropertyID.AEMode);
+ public static readonly CameraValue RoughMonoChrome = new CameraValue("RoughMonoChrome", 30, 0, PropertyID.AEMode);
+ public static readonly CameraValue SoftFocus = new CameraValue("SoftFocus", 31, 0, PropertyID.AEMode);
+ public static readonly CameraValue ToyCamera = new CameraValue("ToyCamera", 32, 0, PropertyID.AEMode);
+ public static readonly CameraValue Fisheye = new CameraValue("Fisheye", 33, 0, PropertyID.AEMode);
+ public static readonly CameraValue WaterColor = new CameraValue("WaterColor", 34, 0, PropertyID.AEMode);
+ public static readonly CameraValue Miniature = new CameraValue("Miniature", 35, 0, PropertyID.AEMode);
+ public static readonly CameraValue Hdr_Standard = new CameraValue("Hdr_Standard", 36, 0, PropertyID.AEMode);
+ public static readonly CameraValue Hdr_Vivid = new CameraValue("Hdr_Vivid", 37, 0, PropertyID.AEMode);
+ public static readonly CameraValue Hdr_Bold = new CameraValue("Hdr_Bold", 38, 0, PropertyID.AEMode);
+ public static readonly CameraValue Hdr_Embossed = new CameraValue("Hdr_Embossed", 39, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie_Fantasy = new CameraValue("Movie_Fantasy", 40, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie_Old = new CameraValue("Movie_Old", 41, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie_Memory = new CameraValue("Movie_Memory", 42, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie_DirectMono = new CameraValue("Movie_DirectMono", 43, 0, PropertyID.AEMode);
+ public static readonly CameraValue Movie_Mini = new CameraValue("Movie_Mini", 44, 0, PropertyID.AEMode);
+ public static readonly CameraValue Unknown = new CameraValue("Unknown", unchecked((int)0xFFFFFFFF), 0, PropertyID.AEMode);
+
+#pragma warning restore 1591
+
+ static AEModeValues()
+ {
+ values = new List();
+ values.Add(Program);
+ values.Add(Tv);
+ values.Add(Av);
+ values.Add(Manual);
+ values.Add(Bulb);
+ values.Add(A_DEP);
+ values.Add(DEP);
+ values.Add(Custom);
+ values.Add(Lock);
+ values.Add(Green);
+ values.Add(NightPortrait);
+ values.Add(Sports);
+ values.Add(Portrait);
+ values.Add(Landscape);
+ values.Add(Closeup);
+ values.Add(FlashOff);
+ values.Add(Custom2);
+ values.Add(Custom3);
+ values.Add(CreativeAuto);
+ values.Add(Movie);
+ values.Add(PhotoInMovie);
+ values.Add(SceneIntelligentAuto);
+ values.Add(Scene);
+ values.Add(NightScenes);
+ values.Add(BacklitScenes);
+ values.Add(Children);
+ values.Add(Food);
+ values.Add(CandlelightPortraits);
+ values.Add(CreativeFilter);
+ values.Add(RoughMonoChrome);
+ values.Add(SoftFocus);
+ values.Add(ToyCamera);
+ values.Add(Fisheye);
+ values.Add(WaterColor);
+ values.Add(Miniature);
+ values.Add(Hdr_Standard);
+ values.Add(Hdr_Vivid);
+ values.Add(Hdr_Bold);
+ values.Add(Hdr_Embossed);
+ values.Add(Movie_Fantasy);
+ values.Add(Movie_Old);
+ values.Add(Movie_Memory);
+ values.Add(Movie_DirectMono);
+ values.Add(Movie_Mini);
+ values.Add(Unknown);
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+
+ ///
+ /// Stores Metering Mode Values and provides methods to get those values
+ ///
+ public sealed class MeteringModeValues : ValueBase
+ {
+ ///
+ /// All values for this property
+ ///
+ public static CameraValue[] Values { get { return values.ToArray(); } }
+ private static List values;
+
+#pragma warning disable 1591
+
+ public static readonly CameraValue Spot = new CameraValue("Spot", 1, 0, PropertyID.MeteringMode);
+ public static readonly CameraValue Evaluative = new CameraValue("Evaluative", 3, 0, PropertyID.MeteringMode);
+ public static readonly CameraValue Partial = new CameraValue("Partial", 4, 0, PropertyID.MeteringMode);
+ public static readonly CameraValue CenterWeightedAveraging = new CameraValue("Center-weighted averaging", 5, 0, PropertyID.MeteringMode);
+ public static readonly CameraValue NotValid = new CameraValue("Not valid", unchecked((int)0xFFFFFFFF), 0, PropertyID.MeteringMode);
+
+#pragma warning restore 1591
+
+ static MeteringModeValues()
+ {
+ values = new List();
+ values.Add(Spot);
+ values.Add(Evaluative);
+ values.Add(Partial);
+ values.Add(CenterWeightedAveraging);
+ values.Add(NotValid);
+ }
+
+ ///
+ /// Get the value from an int.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of the value to get
+ /// The CameraValue with given int representation
+ /// No for the given value
+ public static CameraValue GetValue(int value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a string.
+ /// It has to be an exact match, otherwise an exception is thrown.
+ ///
+ /// The ID of value to get
+ /// The CameraValue with given string representation
+ /// No for the given value
+ public static CameraValue GetValue(string value)
+ {
+ return GetValue(value, values);
+ }
+
+ ///
+ /// Get the value from a double.
+ /// It searches for the closest representation and therefore might not return the exact input value.
+ ///
+ /// The value to get
+ /// The CameraValue with given double representation
+ public static CameraValue GetValue(double value)
+ {
+ return GetValue(value, values);
+ }
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/EDSDKLib.csproj b/src/CamBooth/EDSDKLib/EDSDKLib.csproj
new file mode 100644
index 0000000..2619b54
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/EDSDKLib.csproj
@@ -0,0 +1,65 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {15E99248-6161-46A4-9183-609CA62406A6}
+ Library
+ Properties
+ EDSDKLib
+ EDSDKLib
+ v4.8.1
+ 512
+ 8
+
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ full
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\Release\
+ TRACE
+ true
+ bin\Release\EDSDKLib.xml
+ true
+ pdbonly
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CamBooth/EDSDKLib/Properties/AssemblyInfo.cs b/src/CamBooth/EDSDKLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e12482e
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/Properties/AssemblyInfo.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: CLSCompliant(true)]
+[assembly: AssemblyTitle("EDSDKLib")]
+[assembly: AssemblyDescription("Canon SDK wrapper library")]
+[assembly: AssemblyProduct("EDSDKLib")]
+[assembly: AssemblyCopyright("Copyright © Johannes Bildstein 2016")]
+
+[assembly: ComVisible(false)]
+[assembly: Guid("15e99248-6161-46a4-9183-609ca62406a6")]
+
+[assembly: AssemblyVersion("1.1.1.0")]
+[assembly: AssemblyFileVersion("1.1.1.0")]
diff --git a/src/CamBooth/EDSDKLib/SDK/SDKDelegates.cs b/src/CamBooth/EDSDKLib/SDK/SDKDelegates.cs
new file mode 100644
index 0000000..14527a1
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/SDK/SDKDelegates.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace EOSDigital.SDK
+{
+ ///
+ /// A delegate for progress.
+ ///
+ /// The progress. A value between 0 and 100
+ /// Reference to the object the progress is about
+ /// Pass true to cancel the underlying process
+ ///
+ public delegate ErrorCode SDKProgressCallback(int inPercent, IntPtr inContext, ref bool outCancel);
+ ///
+ /// A delegate for property events.
+ ///
+ /// The property event ID
+ /// The property ID
+ /// A parameter for additional information
+ /// A reference to the object that has sent the event
+ /// Any of the SDK errors
+ public delegate ErrorCode SDKPropertyEventHandler(PropertyEventID inEvent, PropertyID inPropertyID, int inParameter, IntPtr inContext);
+ ///
+ /// A delegate for object events.
+ ///
+ /// The object event ID
+ /// A pointer to the object that has changed
+ /// A reference to the object that has sent the event
+ /// Any of the SDK errors
+ public delegate ErrorCode SDKObjectEventHandler(ObjectEventID inEvent, IntPtr inRef, IntPtr inContext);
+ ///
+ /// A delegate for state events.
+ ///
+ /// The state event ID
+ /// A parameter for additional information
+ /// A reference to the object that has sent the event
+ /// Any of the SDK errors
+ public delegate ErrorCode SDKStateEventHandler(StateEventID inEvent, int inParameter, IntPtr inContext);
+ ///
+ /// A delegate to inform of an added camera.
+ ///
+ /// A reference to the added camera
+ /// Any of the SDK errors
+ public delegate ErrorCode SDKCameraAddedHandler(IntPtr inContext);
+}
diff --git a/src/CamBooth/EDSDKLib/SDK/SDKEnums.cs b/src/CamBooth/EDSDKLib/SDK/SDKEnums.cs
new file mode 100644
index 0000000..4a55c13
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/SDK/SDKEnums.cs
@@ -0,0 +1,1572 @@
+//To disable all the compiler warnings about the missing documentation of enum members
+#pragma warning disable 1591
+
+namespace EOSDigital.SDK
+{
+ ///
+ /// Error Codes
+ ///
+ public enum ErrorCode : int
+ {
+ ///
+ /// ED-SDK Function Success Code
+ ///
+ OK = 0x00000000,
+
+ #region EDSDK Error Code Masks
+
+ ISSPECIFIC_MASK = unchecked((int)0x80000000),
+ COMPONENTID_MASK = 0x7F000000,
+ RESERVED_MASK = 0x00FF0000,
+ ERRORID_MASK = 0x0000FFFF,
+
+ #endregion
+
+ #region EDSDK Base Component IDs
+
+ CMP_ID_CLIENT_COMPONENTID = 0x01000000,
+ CMP_ID_LLSDK_COMPONENTID = 0x02000000,
+ CMP_ID_HLSDK_COMPONENTID = 0x03000000,
+
+ #endregion
+
+ #region EDSDK Generic Error IDs
+
+ #region Miscellaneous errors
+
+ UNIMPLEMENTED = 0x00000001,
+ INTERNAL_ERROR = 0x00000002,
+ MEM_ALLOC_FAILED = 0x00000003,
+ MEM_FREE_FAILED = 0x00000004,
+ OPERATION_CANCELLED = 0x00000005,
+ INCOMPATIBLE_VERSION = 0x00000006,
+ NOT_SUPPORTED = 0x00000007,
+ UNEXPECTED_EXCEPTION = 0x00000008,
+ PROTECTION_VIOLATION = 0x00000009,
+ MISSING_SUBCOMPONENT = 0x0000000A,
+ SELECTION_UNAVAILABLE = 0x0000000B,
+
+ #endregion
+
+ #region File errors
+
+ FILE_IO_ERROR = 0x00000020,
+ FILE_TOO_MANY_OPEN = 0x00000021,
+ FILE_NOT_FOUND = 0x00000022,
+ FILE_OPEN_ERROR = 0x00000023,
+ FILE_CLOSE_ERROR = 0x00000024,
+ FILE_SEEK_ERROR = 0x00000025,
+ FILE_TELL_ERROR = 0x00000026,
+ FILE_READ_ERROR = 0x00000027,
+ FILE_WRITE_ERROR = 0x00000028,
+ FILE_PERMISSION_ERROR = 0x00000029,
+ FILE_DISK_FULL_ERROR = 0x0000002A,
+ FILE_ALREADY_EXISTS = 0x0000002B,
+ FILE_FORMAT_UNRECOGNIZED = 0x0000002C,
+ FILE_DATA_CORRUPT = 0x0000002D,
+ FILE_NAMING_NA = 0x0000002E,
+
+ #endregion
+
+ #region Directory errors
+
+ DIR_NOT_FOUND = 0x00000040,
+ DIR_IO_ERROR = 0x00000041,
+ DIR_ENTRY_NOT_FOUND = 0x00000042,
+ DIR_ENTRY_EXISTS = 0x00000043,
+ DIR_NOT_EMPTY = 0x00000044,
+
+ #endregion
+
+ #region Property errors
+
+ PROPERTIES_UNAVAILABLE = 0x00000050,
+ PROPERTIES_MISMATCH = 0x00000051,
+ PROPERTIES_NOT_LOADED = 0x00000053,
+
+ #endregion
+
+ #region Function Parameter errors
+
+ INVALID_PARAMETER = 0x00000060,
+ INVALID_HANDLE = 0x00000061,
+ INVALID_POINTER = 0x00000062,
+ INVALID_INDEX = 0x00000063,
+ INVALID_LENGTH = 0x00000064,
+ INVALID_FN_POINTER = 0x00000065,
+ INVALID_SORT_FN = 0x00000066,
+
+ #endregion
+
+ #region Device errors
+
+ DEVICE_NOT_FOUND = 0x00000080,
+ DEVICE_BUSY = 0x00000081,
+ DEVICE_INVALID = 0x00000082,
+ DEVICE_EMERGENCY = 0x00000083,
+ DEVICE_MEMORY_FULL = 0x00000084,
+ DEVICE_INTERNAL_ERROR = 0x00000085,
+ DEVICE_INVALID_PARAMETER = 0x00000086,
+ DEVICE_NO_DISK = 0x00000087,
+ DEVICE_DISK_ERROR = 0x00000088,
+ DEVICE_CF_GATE_CHANGED = 0x00000089,
+ DEVICE_DIAL_CHANGED = 0x0000008A,
+ DEVICE_NOT_INSTALLED = 0x0000008B,
+ DEVICE_STAY_AWAKE = 0x0000008C,
+ DEVICE_NOT_RELEASED = 0x0000008D,
+
+ #endregion
+
+ #region Stream errors
+
+ STREAM_IO_ERROR = 0x000000A0,
+ STREAM_NOT_OPEN = 0x000000A1,
+ STREAM_ALREADY_OPEN = 0x000000A2,
+ STREAM_OPEN_ERROR = 0x000000A3,
+ STREAM_CLOSE_ERROR = 0x000000A4,
+ STREAM_SEEK_ERROR = 0x000000A5,
+ STREAM_TELL_ERROR = 0x000000A6,
+ STREAM_READ_ERROR = 0x000000A7,
+ STREAM_WRITE_ERROR = 0x000000A8,
+ STREAM_PERMISSION_ERROR = 0x000000A9,
+ STREAM_COULDNT_BEGIN_THREAD = 0x000000AA,
+ STREAM_BAD_OPTIONS = 0x000000AB,
+ STREAM_END_OF_STREAM = 0x000000AC,
+
+ #endregion
+
+ #region Communications errors
+
+ COMM_PORT_IS_IN_USE = 0x000000C0,
+ COMM_DISCONNECTED = 0x000000C1,
+ COMM_DEVICE_INCOMPATIBLE = 0x000000C2,
+ COMM_BUFFER_FULL = 0x000000C3,
+ COMM_USB_BUS_ERR = 0x000000C4,
+
+ #endregion
+
+ #region Lock/Unlock
+
+ USB_DEVICE_LOCK_ERROR = 0x000000D0,
+ USB_DEVICE_UNLOCK_ERROR = 0x000000D1,
+
+ #endregion
+
+ #region STI/WIA
+
+ STI_UNKNOWN_ERROR = 0x000000E0,
+ STI_INTERNAL_ERROR = 0x000000E1,
+ STI_DEVICE_CREATE_ERROR = 0x000000E2,
+ STI_DEVICE_RELEASE_ERROR = 0x000000E3,
+ DEVICE_NOT_LAUNCHED = 0x000000E4,
+
+ ENUM_NA = 0x000000F0,
+ INVALID_FN_CALL = 0x000000F1,
+ HANDLE_NOT_FOUND = 0x000000F2,
+ INVALID_ID = 0x000000F3,
+ WAIT_TIMEOUT_ERROR = 0x000000F4,
+
+ #endregion
+
+ #region PTP
+
+ SESSION_NOT_OPEN = 0x00002003,
+ INVALID_TRANSACTIONID = 0x00002004,
+ INCOMPLETE_TRANSFER = 0x00002007,
+ INVALID_STRAGEID = 0x00002008,
+ DEVICEPROP_NOT_SUPPORTED = 0x0000200A,
+ INVALID_OBJECTFORMATCODE = 0x0000200B,
+ SELF_TEST_FAILED = 0x00002011,
+ PARTIAL_DELETION = 0x00002012,
+ SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x00002014,
+ NO_VALID_OBJECTINFO = 0x00002015,
+ INVALID_CODE_FORMAT = 0x00002016,
+ UNKNOWN_VENDOR_CODE = 0x00002017,
+ CAPTURE_ALREADY_TERMINATED = 0x00002018,
+ INVALID_PARENTOBJECT = 0x0000201A,
+ INVALID_DEVICEPROP_FORMAT = 0x0000201B,
+ INVALID_DEVICEPROP_VALUE = 0x0000201C,
+ SESSION_ALREADY_OPEN = 0x0000201E,
+ TRANSACTION_CANCELLED = 0x0000201F,
+ SPECIFICATION_OF_DESTINATION_UNSUPPORTED = 0x00002020,
+ NOT_CAMERA_SUPPORT_SDK_VERSION = 0x00002021,
+ #endregion
+
+ #region PTP Vendor
+
+ UNKNOWN_COMMAND = 0x0000A001,
+ OPERATION_REFUSED = 0x0000A005,
+ LENS_COVER_CLOSE = 0x0000A006,
+ LOW_BATTERY = 0x0000A101,
+ OBJECT_NOTREADY = 0x0000A102,
+ CANNOT_MAKE_OBJECT = 0x0000A104,
+ MEMORYSTATUS_NOTREADY = 0x0000A106,
+
+ #endregion
+
+ #region Take Picture errors
+
+ TAKE_PICTURE_AF_NG = 0x00008D01,
+ TAKE_PICTURE_RESERVED = 0x00008D02,
+ TAKE_PICTURE_MIRROR_UP_NG = 0x00008D03,
+ TAKE_PICTURE_SENSOR_CLEANING_NG = 0x00008D04,
+ TAKE_PICTURE_SILENCE_NG = 0x00008D05,
+ TAKE_PICTURE_NO_CARD_NG = 0x00008D06,
+ TAKE_PICTURE_CARD_NG = 0x00008D07,
+ TAKE_PICTURE_CARD_PROTECT_NG = 0x00008D08,
+ TAKE_PICTURE_MOVIE_CROP_NG = 0x00008D09,
+ TAKE_PICTURE_STROBO_CHARGE_NG = 0x00008D0A,
+ TAKE_PICTURE_NO_LENS_NG = 0x00008D0B,
+ TAKE_PICTURE_SPECIAL_MOVIE_MODE_NG = 0x00008D0C,
+ TAKE_PICTURE_LV_REL_PROHIBIT_MODE_NG = 0x00008D0D,
+
+ #endregion
+
+ LAST_GENERIC_ERROR_PLUS_ONE = 0x000000F5,
+
+ #endregion
+ }
+
+ ///
+ /// SDK Data Types
+ ///
+ public enum DataType : int
+ {
+ Unknown = 0,
+ Bool = 1,
+ String = 2,
+ Int8 = 3,
+ UInt8 = 6,
+ Int16 = 4,
+ UInt16 = 7,
+ Int32 = 8,
+ UInt32 = 9,
+ Int64 = 10,
+ UInt64 = 11,
+ Float = 12,
+ Double = 13,
+ ByteBlock = 14,
+ Rational = 20,
+ Point = 21,
+ Rect = 22,
+ Time = 23,
+
+ Bool_Array = 30,
+ Int8_Array = 31,
+ Int16_Array = 32,
+ Int32_Array = 33,
+ UInt8_Array = 34,
+ UInt16_Array = 35,
+ UInt32_Array = 36,
+ Rational_Array = 37,
+
+ FocusInfo = 101,
+ PictureStyleDesc = 102,
+ }
+
+ ///
+ /// Property IDs
+ ///
+ public enum PropertyID : int
+ {
+ Unknown = 0x0000FFFF,
+
+ ProductName = 0x00000002,
+ OwnerName = 0x00000004,
+ MakerName = 0x00000005,
+ DateTime = 0x00000006,
+ FirmwareVersion = 0x00000007,
+ BatteryLevel = 0x00000008,
+ CFn = 0x00000009,
+ SaveTo = 0x0000000b,
+ CurrentStorage = 0x0000000c,
+ CurrentFolder = 0x0000000d,
+ MyMenu = 0x0000000e,
+ BatteryQuality = 0x00000010,
+ BodyIDEx = 0x00000015,
+ HDDirectoryStructure = 0x00000020,
+
+ //Image Properties
+ ImageQuality = 0x00000100,
+ JpegQuality = 0x00000101,
+ Orientation = 0x00000102,
+ ICCProfile = 0x00000103,
+ FocusInfo = 0x00000104,
+ DigitalExposure = 0x00000105,
+ WhiteBalance = 0x00000106,
+ ColorTemperature = 0x00000107,
+ WhiteBalanceShift = 0x00000108,
+ Contrast = 0x00000109,
+ ColorSaturation = 0x0000010a,
+ ColorTone = 0x0000010b,
+ Sharpness = 0x0000010c,
+ ColorSpace = 0x0000010d,
+ ToneCurve = 0x0000010e,
+ PhotoEffect = 0x0000010f,
+ FilterEffect = 0x00000110,
+ ToningEffect = 0x00000111,
+ ParameterSet = 0x00000112,
+ ColorMatrix = 0x00000113,
+ PictureStyle = 0x00000114,
+ PictureStyleDesc = 0x00000115,
+ PictureStyleCaption = 0x00000200,
+
+ //Image Processing Properties
+ Linear = 0x00000300,
+ ClickWBPoint = 0x00000301,
+ WBCoeffs = 0x00000302,
+
+ //Image GPS Properties
+ GPSVersionID = 0x00000800,
+ GPSLatitudeRef = 0x00000801,
+ GPSLatitude = 0x00000802,
+ GPSLongitudeRef = 0x00000803,
+ GPSLongitude = 0x00000804,
+ GPSAltitudeRef = 0x00000805,
+ GPSAltitude = 0x00000806,
+ GPSTimeStamp = 0x00000807,
+ GPSSatellites = 0x00000808,
+ GPSStatus = 0x00000809,
+ GPSMapDatum = 0x00000812,
+ GPSDateStamp = 0x0000081D,
+
+ //Property Mask
+ AtCapture_Flag = unchecked((int)0x80000000),
+
+ //Capture Properties
+ AEMode = 0x00000400,
+ DriveMode = 0x00000401,
+ ISO = 0x00000402,
+ MeteringMode = 0x00000403,
+ AFMode = 0x00000404,
+ Av = 0x00000405,
+ Tv = 0x00000406,
+ ExposureCompensation = 0x00000407,
+ FlashCompensation = 0x00000408,
+ FocalLength = 0x00000409,
+ AvailableShots = 0x0000040a,
+ Bracket = 0x0000040b,
+ WhiteBalanceBracket = 0x0000040c,
+ LensName = 0x0000040d,
+ AEBracket = 0x0000040e,
+ FEBracket = 0x0000040f,
+ ISOBracket = 0x00000410,
+ NoiseReduction = 0x00000411,
+ FlashOn = 0x00000412,
+ RedEye = 0x00000413,
+ FlashMode = 0x00000414,
+ LensStatus = 0x00000416,
+ Artist = 0x00000418,
+ Copyright = 0x00000419,
+ DepthOfField = 0x0000041b,
+ EFCompensation = 0x0000041e,
+ AEModeSelect = 0x00000436,
+
+ //EVF Properties
+ Evf_OutputDevice = 0x00000500,
+ Evf_Mode = 0x00000501,
+ Evf_WhiteBalance = 0x00000502,
+ Evf_ColorTemperature = 0x00000503,
+ Evf_DepthOfFieldPreview = 0x00000504,
+
+ //EVF IMAGE DATA Properties
+ Evf_Zoom = 0x00000507,
+ Evf_ZoomPosition = 0x00000508,
+ Evf_FocusAid = 0x00000509,
+ Evf_ImagePosition = 0x0000050B,
+ Evf_HistogramStatus = 0x0000050C,
+ Evf_AFMode = 0x0000050E,
+
+ Record = 0x00000510,
+
+ Evf_HistogramY = 0x00000515,
+ Evf_HistogramR = 0x00000516,
+ Evf_HistogramG = 0x00000517,
+ Evf_HistogramB = 0x00000518,
+
+ Evf_CoordinateSystem = 0x00000540,
+ Evf_ZoomRect = 0x00000541,
+ Evf_ImageClipRect = 0x00000545,
+ }
+
+ ///
+ /// MyMenu IDs
+ ///
+ public enum MyMenuID : int
+ {
+ Quality = 11,
+ RedEye = 12,
+ Beep = 8,
+ Shoot_WO_Card = 9,
+ ReviewTime = 7,
+ AEB = 13,
+ Whitebalance = 0,
+ CustomWB = 15,
+ WBShift_BKT = 2,
+ Colorspace = 3,
+ PictureStyle = 4,
+ DustDeleteData = 10,
+ ProtectImages = 65536,
+ Rotate = 65537,
+ EraseImages = 65538,
+ PrintOrder = 65539,
+ TransferOrder = 65540,
+ HighlightAlert = 65543,
+ AFPointDisplay = 65544,
+ Histogram = 65545,
+ AutoPlay = 65548,
+ AutoPowerOff = 131072,
+ FileNumbering = 131074,
+ AutoRotate = 131076,
+ InfoButton = 131091,
+ Format = 131093,
+ LCDBrigthness = 131078,
+ DateTime = 131079,
+ Language = 131080,
+ Videosystem = 131081,
+ SensorCleaning = 131088,
+ LiveViewFunctionSettings = 131083,
+ FlashControl = 131094,
+ CameraUserSettings = 131095,
+ ClearAllCameraSettings = 131087,
+ FirmwareVersion = 131089,
+ CFnI_Exposure = 196608,
+ CFnII_Image = 196614,
+ CFn_III_AutoFocus_Drive = 196610,
+ CFnIV_Operation_Others196611,
+ ClearAllCFn = 196612,
+ ExposureLevelIncrements = 262144,
+ ISOSpeedSettingsIncrements = 262145,
+ ISOExpansion = 262159,
+ BracketingAutoCancel = 262147,
+ BracketingSequence = 262148,
+ SafetyShift = 262151,
+ FlashSyncSpeenInAvMode = 262158,
+ LongExpNoiseReduction = 327680,
+ HighISOSpeedNoiseReduction = 327681,
+ HighlightTonePriority = 327682,
+ LensDriveWhenAFImpossible = 393220,
+ LensAFStopButtonFunction = 393221,
+ AFPointSelectionMethod = 393235,
+ SuperimposedDisplay393236,
+ AFAssistBeamFiring = 393229,
+ AFDuringLiveViewShooting = 393233,
+ MirrorLockup = 393230,
+ ShutterButton_AFONButton = 458752,
+ AFON_AELockButtonSwitch = 458753,
+ SetButtonWhenShooting = 458755,
+ DialDirectionDuringTv_Av = 458757,
+ FocusingScreen = 458762,
+ AddOriginalDecisionData = 458766,
+ LiveViewExposureSimulation = 458767,
+ NotSet = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Camera Commands
+ ///
+ public enum CameraCommand : int
+ {
+ TakePicture = 0x00000000,
+ ExtendShutDownTimer = 0x00000001,
+ BulbStart = 0x00000002,
+ BulbEnd = 0x00000003,
+ PressShutterButton = 0x00000004,
+ DoEvfAf = 0x00000102,
+ DriveLensEvf = 0x00000103,
+ DoClickWBEvf = 0x00000104,
+ }
+
+ ///
+ /// Shutter Button State
+ ///
+ public enum ShutterButton : int
+ {
+ OFF = 0x00000000,
+ Halfway = 0x00000001,
+ Completely = 0x00000003,
+ Halfway_NonAF = 0x00010001,
+ Completely_NonAF = 0x00010003,
+ }
+
+ ///
+ /// Camera Status
+ ///
+ public enum CameraStatusCommand : int
+ {
+ UILock = 0x00000000,
+ UIUnLock = 0x00000001,
+ EnterDirectTransfer = 0x00000002,
+ ExitDirectTransfer = 0x00000003,
+ }
+
+ ///
+ /// Property Event IDs
+ ///
+ public enum PropertyEventID : int
+ {
+ ///
+ /// Notifies all property events.
+ ///
+ All = 0x00000100,
+ ///
+ /// Notifies that a camera property value has been changed.
+ /// The changed property can be retrieved from event data.
+ /// The changed value can be retrieved by means of EdsGetPropertyData.
+ /// In the case of type 1 protocol standard cameras,
+ /// notification of changed properties can only be issued for custom functions (CFn).
+ /// If the property type is 0x0000FFFF, the changed property cannot be identified.
+ /// Thus, retrieve all required properties repeatedly.
+ ///
+ PropertyChanged = 0x00000101,
+ ///
+ /// Notifies of changes in the list of camera properties with configurable values.
+ /// The list of configurable values for property IDs indicated in event data
+ /// can be retrieved by means of EdsGetPropertyDesc.
+ /// For type 1 protocol standard cameras, the property ID is identified as "Unknown"
+ /// during notification.
+ /// Thus, you must retrieve a list of configurable values for all properties and
+ /// retrieve the property values repeatedly.
+ /// (For details on properties for which you can retrieve a list of configurable
+ /// properties, see the description of EdsGetPropertyDesc).
+ ///
+ PropertyDescChanged = 0x00000102,
+ }
+
+ ///
+ /// Object Event IDs
+ ///
+ public enum ObjectEventID : int
+ {
+ ///
+ /// Notifies all object events.
+ ///
+ All = 0x00000200,
+ ///
+ /// Notifies that the volume object (memory card) state (VolumeInfo)
+ /// has been changed.
+ /// Changed objects are indicated by event data.
+ /// The changed value can be retrieved by means of EdsGetVolumeInfo.
+ /// Notification of this event is not issued for type 1 protocol standard cameras.
+ ///
+ VolumeInfoChanged = 0x00000201,
+ ///
+ /// Notifies if the designated volume on a camera has been formatted.
+ /// If notification of this event is received, get sub-items of the designated
+ /// volume again as needed.
+ /// Changed volume objects can be retrieved from event data.
+ /// Objects cannot be identified on cameras earlier than the D30
+ /// if files are added or deleted.
+ /// Thus, these events are subject to notification.
+ ///
+ VolumeUpdateItems = 0x00000202,
+ ///
+ /// Notifies if many images are deleted in a designated folder on a camera.
+ /// If notification of this event is received, get sub-items of the designated
+ /// folder again as needed.
+ /// Changed folders (specifically, directory item objects) can be retrieved
+ /// from event data.
+ ///
+ FolderUpdateItems = 0x00000203,
+ ///
+ /// Notifies of the creation of objects such as new folders or files
+ /// on a camera compact flash card or the like.
+ /// This event is generated if the camera has been set to store captured
+ /// images simultaneously on the camera and a computer,
+ /// for example, but not if the camera is set to store images
+ /// on the computer alone.
+ /// Newly created objects are indicated by event data.
+ /// Because objects are not indicated for type 1 protocol standard cameras,
+ /// (that is, objects are indicated as NULL),
+ /// you must again retrieve child objects under the camera object to
+ /// identify the new objects.
+ ///
+ DirItemCreated = 0x00000204,
+ ///
+ /// Notifies of the deletion of objects such as folders or files on a camera
+ /// compact flash card or the like.
+ /// Deleted objects are indicated in event data.
+ /// Because objects are not indicated for type 1 protocol standard cameras,
+ /// you must again retrieve child objects under the camera object to
+ /// identify deleted objects.
+ ///
+ DirItemRemoved = 0x00000205,
+ ///
+ /// Notifies that information of DirItem objects has been changed.
+ /// Changed objects are indicated by event data.
+ /// The changed value can be retrieved by means of EdsGetDirectoryItemInfo.
+ /// Notification of this event is not issued for type 1 protocol standard cameras.
+ ///
+ DirItemInfoChanged = 0x00000206,
+ ///
+ /// Notifies that header information has been updated, as for rotation information
+ /// of image files on the camera.
+ /// If this event is received, get the file header information again, as needed.
+ /// This function is for type 2 protocol standard cameras only.
+ ///
+ DirItemContentChanged = 0x00000207,
+ ///
+ /// Notifies that there are objects on a camera to be transferred to a computer.
+ /// This event is generated after remote release from a computer or local release
+ /// from a camera.
+ /// If this event is received, objects indicated in the event data must be downloaded.
+ /// Furthermore, if the application does not require the objects, instead
+ /// of downloading them,
+ /// execute EdsDownloadCancel and release resources held by the camera.
+ /// The order of downloading from type 1 protocol standard cameras must be the order
+ /// in which the events are received.
+ ///
+ DirItemRequestTransfer = 0x00000208,
+ ///
+ /// Notifies if the camera's direct transfer button is pressed.
+ /// If this event is received, objects indicated in the event data must be downloaded.
+ /// Furthermore, if the application does not require the objects, instead of
+ /// downloading them,
+ /// execute EdsDownloadCancel and release resources held by the camera.
+ /// Notification of this event is not issued for type 1 protocol standard cameras.
+ ///
+ DirItemRequestTransferDT = 0x00000209,
+ ///
+ /// Notifies of requests from a camera to cancel object transfer
+ /// if the button to cancel direct transfer is pressed on the camera.
+ /// If the parameter is 0, it means that cancellation of transfer is requested for
+ /// objects still not downloaded,
+ /// with these objects indicated by kEdsObjectEvent_DirItemRequestTransferDT.
+ /// Notification of this event is not issued for type 1 protocol standard cameras.
+ ///
+ DirItemCancelTransferDT = 0x0000020A,
+ VolumeAdded = 0x0000020C,
+ VolumeRemoved = 0x0000020D,
+ }
+
+ ///
+ /// State Event IDs
+ ///
+ public enum StateEventID : int
+ {
+ ///
+ /// Notifies all state events.
+ ///
+ All = 0x00000300,
+ ///
+ /// Indicates that a camera is no longer connected to a computer,
+ /// whether it was disconnected by unplugging a cord, opening
+ /// the compact flash compartment,
+ /// turning the camera off, auto shut-off, or by other means.
+ ///
+ Shutdown = 0x00000301,
+ ///
+ /// Notifies of whether or not there are objects waiting to
+ /// be transferred to a host computer.
+ /// This is useful when ensuring all shot images have been transferred
+ /// when the application is closed.
+ /// Notification of this event is not issued for type 1 protocol
+ /// standard cameras.
+ ///
+ JobStatusChanged = 0x00000302,
+ ///
+ /// Notifies that the camera will shut down after a specific period.
+ /// Generated only if auto shut-off is set.
+ /// Exactly when notification is issued (that is, the number of
+ /// seconds until shutdown) varies depending on the camera model.
+ /// To continue operation without having the camera shut down,
+ /// use EdsSendCommand to extend the auto shut-off timer.
+ /// The time in seconds until the camera shuts down is returned
+ /// as the initial value.
+ ///
+ WillSoonShutDown = 0x00000303,
+ ///
+ /// As the counterpart event to kEdsStateEvent_WillSoonShutDown,
+ /// this event notifies of updates to the number of seconds until
+ /// a camera shuts down.
+ /// After the update, the period until shutdown is model-dependent.
+ ///
+ ShutDownTimerUpdate = 0x00000304,
+ ///
+ /// Notifies that a requested release has failed, due to focus
+ /// failure or similar factors.
+ ///
+ CaptureError = 0x00000305,
+ ///
+ /// Notifies of internal SDK errors.
+ /// If this error event is received, the issuing device will probably
+ /// not be able to continue working properly,
+ /// so cancel the remote connection.
+ ///
+ InternalError = 0x00000306,
+ ///
+ /// The autofocus is done working.
+ ///
+ AfResult = 0x00000309,
+ ///
+ /// The bulb exposure time has changed.
+ ///
+ BulbExposureTime = 0x00000310,
+ }
+
+ ///
+ /// Drive Lens
+ ///
+ public enum DriveLens : int
+ {
+ Near1 = 0x00000001,
+ Near2 = 0x00000002,
+ Near3 = 0x00000003,
+ Far1 = 0x00008001,
+ Far2 = 0x00008002,
+ Far3 = 0x00008003,
+ }
+
+ ///
+ /// Seek Origin
+ ///
+ public enum SeekOrigin : int
+ {
+ Current = 0,
+ Begin = 1,
+ End = 2,
+ }
+
+ ///
+ /// File Access
+ ///
+ public enum FileAccess : int
+ {
+ Read = 0,
+ Write = 1,
+ ReadWrite = 2,
+ Error = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// File-creation Disposition
+ ///
+ public enum FileCreateDisposition : int
+ {
+ ///
+ /// Creates a new file. An error occurs if the designated file already exists
+ ///
+ CreateNew = 0,
+ ///
+ /// Creates a new file. If the designated file already
+ /// exists, that file is overwritten and existing attributes
+ ///
+ CreateAlways = 1,
+ ///
+ /// Opens a file. An error occurs if the designated file does not exist.
+ ///
+ OpenExisting = 2,
+ ///
+ /// If the file exists, it is opened. If the designated file
+ /// does not exist, a new file is created.
+ ///
+ OpenAlways = 3,
+ ///
+ /// Opens a file and sets the file size to 0 bytes.
+ ///
+ TruncateExisting = 4,
+ }
+
+ ///
+ /// Image Type
+ ///
+ public enum ImageType : int
+ {
+ Unknown = 0x00000000,
+ Jpeg = 0x00000001,
+ CRW = 0x00000002,
+ RAW = 0x00000004,
+ CR2 = 0x00000006,
+ }
+
+ ///
+ /// Image Size
+ ///
+ public enum ImageSize : int
+ {
+ Large = 0,
+ Middle = 1,
+ Small = 2,
+ Middle1 = 5,
+ Middle2 = 6,
+ Small1 = 14,
+ Small2 = 15,
+ Small3 = 16,
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Compression Quality
+ ///
+ public enum CompressQuality : int
+ {
+ Normal = 2,
+ Fine = 3,
+ Lossless = 4,
+ SuperFine = 5,
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Image Quality
+ ///
+ public enum ImageQuality : int
+ {
+ ///
+ /// Jpeg Large
+ ///
+ LargeJpeg = 0x0010FF0F,
+ ///
+ /// Jpeg Middle1
+ ///
+ Middle1Jpeg = 0x0510FF0F,
+ ///
+ /// Jpeg Middle2
+ ///
+ Middle2Jpeg = 0x0610FF0F,
+ ///
+ /// Jpeg Small
+ ///
+ SmallJpeg = 0x0210FF0F,
+ ///
+ /// Jpeg Small2
+ ///
+ Small2Jpeg = 0x0F13FF0F,
+ ///
+ /// Jpeg Small3
+ ///
+ Small3Jpeg = 0x1013FF0F,
+ ///
+ /// Jpeg Large Fine
+ ///
+ LargeJpegFine = 0x0013FF0F,
+ ///
+ /// Jpeg Large Normal
+ ///
+ LargeJpegNormal = 0x0012FF0F,
+ ///
+ /// Jpeg Middle Fine
+ ///
+ MiddleJpegFine = 0x0113FF0F,
+ ///
+ /// Jpeg Middle Normal
+ ///
+ MiddleJpegNormal = 0x0112FF0F,
+ ///
+ /// Jpeg Small Fine
+ ///
+ SmallJpegFine = 0x0213FF0F,
+ ///
+ /// Jpeg Small Normal
+ ///
+ SmallJpegNormal = 0x0212FF0F,
+ ///
+ /// Jpeg Small1 Fine
+ ///
+ Small1JpegFine = 0x0E13FF0F,
+ ///
+ /// Jpeg Small1 Normal
+ ///
+ Small1JpegNormal = 0x0E12FF0F,
+
+ ///
+ /// RAW
+ ///
+ RAW = 0x0064FF0F,
+ ///
+ /// RAW + Jpeg Large Fine
+ ///
+ RAW_LargeJpegFine = 0x00640013,
+ ///
+ /// RAW + Jpeg Large Normal
+ ///
+ RAW_LargeJpegNormal = 0x00640012,
+ ///
+ /// RAW + Jpeg Middle Fine
+ ///
+ RAW_MiddleJpegFine = 0x00640113,
+ ///
+ /// RAW + Jpeg Middle Normal
+ ///
+ RAW_MiddleJpegNormal = 0x00640112,
+ ///
+ /// RAW + Jpeg Small Fine
+ ///
+ RAW_SmallJpegFine = 0x00640213,
+ ///
+ /// RAW + Jpeg Small Normal
+ ///
+ RAW_SmallJpegNormal = 0x00640212,
+ ///
+ /// RAW + Jpeg Small1 Fine
+ ///
+ RAW_Small1JpegFine = 0x00640E13,
+ ///
+ /// RAW + Jpeg Small1 Normal
+ ///
+ RAW_Small1JpegNormal = 0x00640E12,
+ ///
+ /// RAW + Jpeg Small2
+ ///
+ RAW_Small2Jpeg = 0x00640F13,
+ ///
+ /// RAW + Jpeg Small3
+ ///
+ RAW_Small3Jpeg = 0x00641013,
+ ///
+ /// RAW + Jpeg Large
+ ///
+ RAW_LargeJpeg = 0x00640010,
+ ///
+ /// RAW + Jpeg Middle1
+ ///
+ RAW_Middle1Jpeg = 0x00640510,
+ ///
+ /// RAW + Jpeg Middle2
+ ///
+ RAW_Middle2Jpeg = 0x00640610,
+ ///
+ /// RAW + Jpeg Small
+ ///
+ RAW_SmallJpeg = 0x00640210,
+
+ ///
+ /// MRAW(SRAW1)
+ ///
+ MRAW = 0x0164FF0F,
+ ///
+ /// MRAW(SRAW1) + Jpeg Large Fine
+ ///
+ MRAW_LargeJpegFine = 0x01640013,
+ ///
+ /// MRAW(SRAW1) + Jpeg Large Normal
+ ///
+ MRAW_LargeJpegNormal = 0x01640012,
+ ///
+ /// MRAW(SRAW1) + Jpeg Middle Fine
+ ///
+ MRAW_MiddleJpegFine = 0x01640113,
+ ///
+ /// MRAW(SRAW1) + Jpeg Middle Normal
+ ///
+ MRAW_MiddleJpegNormal = 0x01640112,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small Fine
+ ///
+ MRAW_SmallJpegFine = 0x01640213,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small Normal
+ ///
+ MRAW_SmallJpegNormal = 0x01640212,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small1 Fine
+ ///
+ MRAW_Small1JpegFine = 0x01640E13,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small1 Normal
+ ///
+ MRAW_Small1JpegNormal = 0x01640E12,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small2
+ ///
+ MRAW_Small2Jpeg = 0x01640F13,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small3
+ ///
+ MRAW_Small3Jpeg = 0x01641013,
+ ///
+ /// MRAW(SRAW1) + Jpeg Large
+ ///
+ MRAW_LargeJpeg = 0x01640010,
+ ///
+ /// MRAW(SRAW1) + Jpeg Middle1
+ ///
+ MRAW_Middle1Jpeg = 0x01640510,
+ ///
+ /// MRAW(SRAW1) + Jpeg Middle2
+ ///
+ MRAW_Middle2Jpeg = 0x01640610,
+ ///
+ /// MRAW(SRAW1) + Jpeg Small
+ ///
+ MRAW_SmallJpeg = 0x01640210,
+
+ ///
+ /// SRAW(SRAW2)
+ ///
+ SRAW = 0x0264FF0F,
+ ///
+ /// SRAW(SRAW2) + Jpeg Large Fine
+ ///
+ SRAW_LargeJpegFine = 0x02640013,
+ ///
+ /// SRAW(SRAW2) + Jpeg Large Normal
+ ///
+ SRAW_LargeJpegNormal = 0x02640012,
+ ///
+ /// SRAW(SRAW2) + Jpeg Middle Fine
+ ///
+ SRAW_MiddleJpegFine = 0x02640113,
+ ///
+ /// SRAW(SRAW2) + Jpeg Middle Normal
+ ///
+ SRAW_MiddleJpegNormal = 0x02640112,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small Fine
+ ///
+ SRAW_SmallJpegFine = 0x02640213,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small Normal
+ ///
+ SRAW_SmallJpegNormal = 0x02640212,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small1 Fine
+ ///
+ SRAW_Small1JpegFine = 0x02640E13,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small1 Normal
+ ///
+ SRAW_Small1JpegNormal = 0x02640E12,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small2
+ ///
+ SRAW_Small2Jpeg = 0x02640F13,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small3
+ ///
+ SRAW_Small3Jpeg = 0x02641013,
+ ///
+ /// SRAW(SRAW2) + Jpeg Large
+ ///
+ SRAW_LargeJpeg = 0x02640010,
+ ///
+ /// SRAW(SRAW2) + Jpeg Middle1
+ ///
+ SRAW_Middle1Jpeg = 0x02640510,
+ ///
+ /// SRAW(SRAW2) + Jpeg Middle2
+ ///
+ SRAW_Middle2Jpeg = 0x02640610,
+ ///
+ /// SRAW(SRAW2) + Jpeg Small
+ ///
+ SRAW_SmallJpeg = 0x02640210,
+
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Image Quality for Legacy Cameras
+ ///
+ public enum ImageQualityLegacy : int
+ {
+ ///
+ /// Jpeg Large
+ ///
+ LJ = 0x001F000F,
+ ///
+ /// Jpeg Middle1
+ ///
+ M1J = 0x051F000F,
+ ///
+ /// Jpeg Middle2
+ ///
+ M2J = 0x061F000F,
+ ///
+ /// Jpeg Small
+ ///
+ SJ = 0x021F000F,
+ ///
+ /// Jpeg Large Fine
+ ///
+ LJF = 0x00130000,
+ ///
+ /// Jpeg Large Normal
+ ///
+ LJN = 0x00120000,
+ ///
+ /// Jpeg Middle Fine
+ ///
+ MJF = 0x01130000,
+ ///
+ /// Jpeg Middle Normal
+ ///
+ MJN = 0x01120000,
+ ///
+ /// Jpeg Small Fine
+ ///
+ SJF = 0x02130000,
+ ///
+ /// Jpeg Small Normal
+ ///
+ SJN = 0x02120000,
+
+ ///
+ /// RAW
+ ///
+ LR = 0x00240000,
+ ///
+ /// RAW + Jpeg Large Fine
+ ///
+ LRLJF = 0x00240013,
+ ///
+ /// RAW + Jpeg Large Normal
+ ///
+ LRLJN = 0x00240012,
+ ///
+ /// RAW + Jpeg Middle Fine
+ ///
+ LRMJF = 0x00240113,
+ ///
+ /// RAW + Jpeg Middle Normal
+ ///
+ LRMJN = 0x00240112,
+ ///
+ /// RAW + Jpeg Small Fine
+ ///
+ LRSJF = 0x00240213,
+ ///
+ /// RAW + Jpeg Small Normal
+ ///
+ LRSJN = 0x00240212,
+
+ ///
+ /// RAW
+ ///
+ LR2 = 0x002F000F,
+ ///
+ /// RAW + Jpeg Large
+ ///
+ LR2LJ = 0x002F001F,
+ ///
+ /// RAW + Jpeg Middle1
+ ///
+ LR2M1J = 0x002F051F,
+ ///
+ /// RAW + Jpeg Middle2
+ ///
+ LR2M2J = 0x002F061F,
+ ///
+ /// RAW + Jpeg Small
+ ///
+ LR2SJ = 0x002F021F,
+
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Image Source
+ ///
+ public enum ImageSource : int
+ {
+ FullView = 0,
+ Thumbnail = 1,
+ Preview = 2,
+ RAWThumbnail = 3,
+ RAWFullView = 4,
+ }
+
+ ///
+ /// Target Image Type
+ ///
+ public enum TargetImageType : int
+ {
+ Unknown = 0x00000000,
+ Jpeg = 0x00000001,
+ TIFF = 0x00000007,
+ TIFF16 = 0x00000008,
+ RGB = 0x00000009,
+ RGB16 = 0x0000000A,
+ DIB = 0x0000000B,
+ }
+
+ ///
+ /// Progress Option
+ ///
+ public enum ProgressOption : int
+ {
+ NoReport = 0,
+ Done = 1,
+ Periodically = 2,
+ }
+
+ ///
+ /// File Attribute
+ ///
+ public enum FileAttribute : int
+ {
+ Normal = 0x00000000,
+ ReadOnly = 0x00000001,
+ Hidden = 0x00000002,
+ System = 0x00000004,
+ Archive = 0x00000020,
+ }
+
+ ///
+ /// Battery Level
+ ///
+ public enum BatteryQuality : int
+ {
+ Empty = 0,
+ Low = 9,
+ Half = 49,
+ Normal = 80,
+ High = 69,
+ Quarter = 19,
+ //Error = 0,
+ //BCLevel = 0,
+ AC = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Save to Device
+ ///
+ public enum SaveTo : int
+ {
+ Camera = 1,
+ Host = 2,
+ Both = 3,
+ }
+
+ ///
+ /// Storage Type
+ ///
+ public enum StorageType : int
+ {
+ None = 0,
+ CF = 1,
+ SD = 2,
+ HD = 4,
+ CFast = 5,
+ }
+
+ ///
+ /// Whitebalance
+ ///
+ public enum WhiteBalance : int
+ {
+ Pasted = -2,
+ Click = -1,
+ Auto = 0,
+ Daylight = 1,
+ Cloudy = 2,
+ Tangsten = 3,
+ Fluorescent = 4,
+ Strobe = 5,
+ WhitePaper = 6,
+ Shade = 8,
+ ColorTemperature = 9,
+ PCSet1 = 10,
+ PCSet2 = 11,
+ PCSet3 = 12,
+ WhitePaper2 = 15,
+ WhitePaper3 = 16,
+ WhitePaper4 = 18,
+ WhitePaper5 = 19,
+ PCSet4 = 20,
+ PCSet5 = 21,
+ }
+
+ ///
+ /// Photo Effect
+ ///
+ public enum PhotoEffect : int
+ {
+ Off = 0,
+ Monochrome = 5,
+ }
+
+ ///
+ /// Color Matrix
+ ///
+ public enum ColorMatrix : int
+ {
+ Custom = 0,
+ ColorMatrix1 = 1,
+ ColorMatrix2 = 2,
+ ColorMatrix3 = 3,
+ ColorMatrix4 = 4,
+ ColorMatrix5 = 5,
+ ColorMatrix6 = 6,
+ ColorMatrix7 = 7,
+ }
+
+ ///
+ /// Filter Effect
+ ///
+ public enum FilterEffect : int
+ {
+ None = 0,
+ Yellow = 1,
+ Orange = 2,
+ Red = 3,
+ Green = 4,
+ }
+
+ ///
+ /// Toning Effect
+ ///
+ public enum ToningEffect : int
+ {
+ None = 0,
+ Sepia = 1,
+ Blue = 2,
+ Purple = 3,
+ Green = 4,
+ }
+
+ ///
+ /// Color Space
+ ///
+ public enum ColorSpace : int
+ {
+ sRGB = 1,
+ AdobeRGB = 2,
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Picture Style
+ ///
+ public enum PictureStyle : int
+ {
+ Standard = 0x0081,
+ Portrait = 0x0082,
+ Landscape = 0x0083,
+ Neutral = 0x0084,
+ Faithful = 0x0085,
+ Monochrome = 0x0086,
+ Auto = 0x0087,
+ User1 = 0x0021,
+ User2 = 0x0022,
+ User3 = 0x0023,
+ PC1 = 0x0041,
+ PC2 = 0x0042,
+ PC3 = 0x0043,
+ }
+
+ ///
+ /// Transfer Option
+ ///
+ public enum TransferOption : int
+ {
+ ByDirectTransfer = 1,
+ ByRelease = 2,
+ ToDesktop = 0x00000100,
+ }
+
+ ///
+ /// Bracketing Mode
+ ///
+ public enum BracketMode : int
+ {
+ Exposure = 0x01,
+ ISO = 0x02,
+ Whitebalance = 0x04,
+ FlashExposure = 0x08,
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Liveview Output Device
+ ///
+ public enum EvfOutputDevice : int
+ {
+ Off = 0,
+ Camera = 1,
+ PC = 2,
+ Filming = 3,
+ Mobile = 4,
+ Mobile2 = 8,
+ }
+
+ ///
+ /// Liveview Zoom Level
+ ///
+ public enum EvfZoom : int
+ {
+ Fit = 1,
+ x5 = 5,
+ x10 = 10,
+ }
+
+ ///
+ /// Liveview Autofocus Mode
+ ///
+ public enum EvfAFMode : int
+ {
+ Quick = 0,
+ Live = 1,
+ LiveFace = 2,
+ LiveMulti = 3,
+ }
+
+ ///
+ /// Flash Type
+ ///
+ public enum FlashType : int
+ {
+ None = 0,
+ Internal = 1,
+ ExternalETTL = 2,
+ ExternalATTL = 3,
+ Invalid = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Flash ETTL 2 Mode
+ ///
+ public enum ETTL2Mode : int
+ {
+ Evaluative = 0,
+ Average = 1,
+ }
+
+ ///
+ /// Processing parameter of a camera
+ ///
+ public enum ProcessingParameter : int
+ {
+ Standard = 0,
+ ProcessingParameter1 = 1,
+ ProcessingParameter2 = 2,
+ ProcessingParameter3 = 3,
+ }
+
+ ///
+ /// The orientation of an image
+ ///
+ public enum ImageOrientation : int
+ {
+ ///
+ /// The 0th row is at the visual top of the image, and the 0th column is on the visual left-hand side
+ ///
+ ULRD = 1,
+ ///
+ /// The 0th row is at the visual bottom of the image, and the 0th column is on the visual right-hand side
+ ///
+ DRLU = 3,
+ ///
+ /// The 0th row is on the visual right-hand side of the image, and the 0th column is at the visual top
+ ///
+ LDUR = 6,
+ ///
+ /// The 0th row is on the visual left-hand side of the image, and the 0th column is at the visual bottom
+ ///
+ RUDL = 8,
+
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Tone curve
+ ///
+ public enum ToneCurve : int
+ {
+ Standard = 0x00000000,
+ UserSetting = 0x00000011,
+ CustomSetting = 0x00000080,
+ TCD1 = 0x00000001,
+ TCD2 = 0x00000002,
+ TCD3 = 0x00000003,
+ }
+
+ ///
+ /// Drive mode of a camera
+ ///
+ public enum DriveMode : int
+ {
+ SingleFrame = 0x00000000,
+ Continuous = 0x00000001,
+ Video = 0x00000002,
+ HighSpeedContinuous = 0x00000004,
+ LowSpeedContinuous = 0x00000005,
+ SilentSingleFrame = 0x00000006,
+ SelfTimer10sContinuous = 0x00000007,
+ SelfTimer10s = 0x00000010,
+ SelfTimer2s = 0x00000011,
+ }
+
+ ///
+ /// Autofocus mode of a camera
+ ///
+ public enum AFMode : int
+ {
+ OneShot = 0,
+ AIServo = 1,
+ AIFocus = 2,
+ Manual = 3,
+ Unknown = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Noise reduction method
+ ///
+ public enum NoiseReduction : int
+ {
+ Off = 0,
+ On1 = 1,
+ On2 = 2,
+ On = 3,
+ Auto = 4,
+ }
+
+ ///
+ /// State of red eye reduction
+ ///
+ public enum RedEye : int
+ {
+ Off = 0,
+ On = 1,
+ Invalid = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Flash synchronization of curtain
+ ///
+ public enum SynchroTiming : int
+ {
+ Curtain1 = 0,
+ Curtain2 = 1,
+ Invalid = unchecked((int)0xFFFFFFFF),
+ }
+
+ ///
+ /// Mode of histogram
+ ///
+ public enum HistogramStatus : int
+ {
+ Hide = 0,
+ Normal = 1,
+ Grayout = 2,
+ }
+
+ ///
+ /// Video recording methods
+ ///
+ public enum Recording : int
+ {
+ Off = 0,
+ Ready = 3,
+ On = 4,
+ }
+
+ ///
+ /// Image type to save after RAW processing
+ ///
+ public enum SaveImageType : int
+ {
+ Jpeg = 0x00000001,
+ TIFF = 0x00000007,
+ TIFF16 = 0x00000008,
+ }
+
+ ///
+ /// Camera sub-type
+ ///
+ public enum DeviceSubType : int
+ {
+ CanonPTPCameras = 1,
+ CanonPTP_IPCameras = 2,
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/SDK/SDKMethods.cs b/src/CamBooth/EDSDKLib/SDK/SDKMethods.cs
new file mode 100644
index 0000000..e88ed63
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/SDK/SDKMethods.cs
@@ -0,0 +1,1521 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace EOSDigital.SDK
+{
+ ///
+ /// This class contains all of the native Canon SDK calls and some wrapper methods
+ ///
+ public static class CanonSDK
+ {
+ ///
+ /// Maximum length of string
+ ///
+ public const int MAX_NAME = 256;
+ ///
+ /// Block size of a data transfer
+ ///
+ public const int TRANSFER_BLOCK_SIZE = 512;
+
+ ///
+ /// The path to the Canon SDK DLL
+ ///
+ public const string DllPath = "EDSDK";
+
+ #region Version Check
+
+ ///
+ /// Version of the currently used Canon SDK DLL
+ ///
+ public static Version SDKVersion
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// States if the used SDK version is >=3.4
+ /// Call to initialize this property.
+ ///
+ public static bool IsVerGE34
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Checks which SDK version is currently used and sets IsVer* properties
+ ///
+ /// Could not extract version information
+ public static void InitializeVersion()
+ {
+ try
+ {
+ SDKVersion = GetSDKVersion();
+ if (SDKVersion == null) throw new InvalidOperationException("Could not find SDK version");
+
+ IsVerGE34 = SDKVersion.Major >= 3 && SDKVersion.Minor >= 4;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException("Could not find SDK version", ex);
+ }
+ }
+
+ ///
+ /// Get SDK version on Windows
+ ///
+ /// The SDK version or null if not found
+ private static Version GetSDKVersion()
+ {
+ var modules = Process.GetCurrentProcess().Modules;
+ foreach (var module in modules)
+ {
+ var pm = module as ProcessModule;
+ string name = pm?.ModuleName?.ToLower();
+ if (name == "edsdk.dll")
+ {
+ FileVersionInfo vi = pm.FileVersionInfo;
+ return new Version(vi.ProductMajorPart, vi.ProductMinorPart, vi.ProductBuildPart, vi.ProductPrivatePart);
+ }
+ }
+ return null;
+ }
+
+ #endregion
+
+ #region Init/Close
+
+ ///
+ /// Initializes the libraries.
+ /// This must be called before using the EDSDK API
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsInitializeSDK();
+
+ ///
+ /// Terminates the use of the libraries.
+ /// This must be called when ending the SDK, it releases all resources used by the libraries.
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsTerminateSDK();
+
+ ///
+ /// Establishes a logical connection with a remote camera. Use this method after getting the camera object.
+ ///
+ /// The reference of the camera.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsOpenSession(IntPtr inCameraRef);
+
+ ///
+ /// Closes a logical connection with a remote camera.
+ ///
+ /// The reference of the camera.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCloseSession(IntPtr inCameraRef);
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets the byte size and data type of a designated property from a camera object or image object.
+ ///
+ /// The reference of the item.
+ /// The property ID
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// Pointer to the buffer that is to receive the property type data.
+ /// Pointer to the buffer that is to receive the property size.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPropertySize(IntPtr inRef, PropertyID inPropertyID, int inParam, out DataType outDataType, out int outSize);
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The number of bytes of the prepared buffer for receive property-value.
+ /// The buffer pointer to receive property-value.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, int inPropertySize, IntPtr outPropertyData);
+
+ ///
+ /// Sets property data for the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID
+ /// Additional information of property.
+ /// The number of bytes of the prepared buffer for set property-value.
+ /// The buffer pointer to set property-value.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, int inPropertySize, [MarshalAs(UnmanagedType.AsAny), In] object inPropertyData);
+
+ ///
+ /// Gets a list of property data that can be set for the object designated in inRef,
+ /// as well as maximum and minimum values. This method is only intended for some shooting-related properties
+ ///
+ /// The reference of the camera.
+ /// The property ID.
+ /// Array of the values which can be set up.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPropertyDesc(IntPtr inRef, PropertyID inPropertyID, out PropertyDesc outPropertyDesc);
+
+ #endregion
+
+ #region Commands
+
+ ///
+ /// Sends a command such as "Shoot" to a remote camera.
+ ///
+ /// The reference of the camera which will receive the command.
+ /// Specifies the command to be sent
+ /// Specifies additional command-specific information.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSendCommand(IntPtr inCameraRef, CameraCommand inCommand, int inParam);
+
+ ///
+ /// Sets the remote camera state or mode.
+ ///
+ /// The reference of the camera which will receive the command.
+ /// Specifies the command to be sent.
+ /// Specifies additional command-specific information.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSendStatusCommand(IntPtr inCameraRef, CameraStatusCommand inCameraState, int inParam);
+
+ #endregion
+
+ #region Camera File System
+
+ ///
+ /// Sets the remaining HDD capacity on the host computer (excluding the portion from image transfer), as calculated by subtracting the portion from the previous time.
+ /// Set a reset flag initially and designate the cluster length and number of free clusters.
+ /// Some type 2 protocol standard cameras can display the number of shots left on the camera based on the available disk capacity of the host computer.
+ /// For these cameras, after the storage destination is set to the computer, use this method to notify the camera of the available disk capacity of the host computer.
+ ///
+ /// The reference of the camera which will receive the command.
+ /// The remaining capacity of a transmission place.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetCapacity(IntPtr inCameraRef, Capacity inCapacity);
+
+ ///
+ /// Gets volume information for a memory card in the camera
+ ///
+ /// Information of the volume
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetVolumeInfo(IntPtr inCameraRef, out VolumeInfo outVolumeInfo);
+
+ ///
+ /// Formats a volume.
+ ///
+ /// The reference of the volume.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsFormatVolume(IntPtr inVolumeRef);
+
+ ///
+ /// Gets information about the directory or file object on the memory card (volume) in a remote camera.
+ ///
+ /// The reference of the directory item.
+ /// Information of the directory item.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetDirectoryItemInfo(IntPtr inDirItemRef, out DirectoryItemInfo outDirItemInfo);
+
+ ///
+ /// Deletes a camera folder or file.
+ /// If folders with subdirectories are designated, all files are deleted except protected files.
+ /// DirectoryItem objects deleted by means of this method are implicitly released.
+ /// Thus, there is no need to release them by means of Release.
+ ///
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDeleteDirectoryItem(IntPtr inDirItemRef);
+
+ ///
+ /// Gets attributes of files of a camera.
+ ///
+ /// The reference of the directory item.
+ ///
+ /// Indicates the file attributes.
+ /// As for the file attributes, OR values of the value defined by enum FileAttributes can be retrieved.
+ /// Thus, when determining the file attributes, it must be checked if an attribute flag is set for target attributes.
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetAttribute(IntPtr inDirItemRef, out FileAttribute outFileAttribute);
+
+ ///
+ /// Changes attributes of files on a camera.
+ ///
+ /// The reference of the directory item.
+ ///
+ /// Indicates the file attributes.
+ /// As for the file attributes, OR values of the value defined by enum FileAttributes can be retrieved.
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetAttribute(IntPtr inDirItemRef, FileAttribute inFileAttribute);
+
+ #endregion
+
+ #region Download
+
+ ///
+ /// Downloads a file on a remote camera (in the camera memory or on a memory card) to the host computer.
+ /// The downloaded file is sent directly to a file stream created in advance.
+ /// When dividing the file being retrieved, call this method repeatedly.
+ /// Also in this case, make the data block size a multiple of 512 (bytes), excluding the final block.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the directory item.
+ /// -
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownload(IntPtr inDirItemRef, int inReadSize, IntPtr outStream);
+
+ ///
+ /// Downloads a file on a remote camera (in the camera memory or on a memory card) to the host computer.
+ /// The downloaded file is sent directly to a file stream created in advance.
+ /// When dividing the file being retrieved, call this method repeatedly.
+ /// Also in this case, make the data block size a multiple of 512 (bytes), excluding the final block.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the directory item.
+ /// -
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownload(IntPtr inDirItemRef, long inReadSize, IntPtr outStream);
+
+ ///
+ /// Must be executed when downloading of a directory item is canceled.
+ /// Calling this method makes the camera cancel file transmission.
+ /// It also releases resources.
+ /// This operation need not be executed when using DownloadThumbnail.
+ ///
+ /// The reference of the directory item.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownloadCancel(IntPtr inDirItemRef);
+
+ ///
+ /// Must be called when downloading of directory items is complete.
+ /// Executing this method makes the camera recognize that file transmission is complete.
+ /// This operation need not be executed when using DownloadThumbnail.
+ ///
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownloadComplete(IntPtr inDirItemRef);
+
+ ///
+ /// Extracts and downloads thumbnail information from image files in a camera.
+ /// Thumbnail information in the camera's image files is downloaded to the host computer.
+ /// Downloaded thumbnails are sent directly to a file stream created in advance.
+ ///
+ /// The reference of the directory item.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownloadThumbnail(IntPtr inDirItemRef, IntPtr outStream);
+
+ #endregion
+
+ #region Streams
+
+ ///
+ /// Creates a new file on a host computer (or opens an existing file) and creates a file stream for access to the file.
+ /// If a new file is designated before executing this method, the file is actually created following the timing of writing by means of Write or the like with respect to an open stream.
+ ///
+ /// Pointer to a null-terminated string that specifies the file name.
+ /// Action to take on files that exist, and which action to take hen files do not exist.
+ /// Access to the stream (reading, writing, or both).
+ /// The reference of the stream
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateFileStream(string inFileName, FileCreateDisposition inCreateDisposition, FileAccess inDesiredAccess, out IntPtr outStream);
+
+ ///
+ /// Creates a stream in the memory of a host computer.
+ /// In the case if writing in excess of the allocated buffer size, the memory is automatically extended.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStream(int inBufferSize, out IntPtr outStream);
+
+ ///
+ /// Creates a stream in the memory of a host computer.
+ /// In the case if writing in excess of the allocated buffer size, the memory is automatically extended.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStream(long inBufferSize, out IntPtr outStream);
+
+ ///
+ /// An extended version of CreateStreamFromFile.
+ /// Use this method when working with Unicode file names.
+ ///
+ /// Designate the file name.
+ /// Action to take on files take when files do not exist.
+ /// Access to the stream (reading, writing, or both)
+ /// The reference of the stream
+ /// Any of the SDK errors
+ [DllImport(DllPath, CharSet = CharSet.Unicode)]
+ public extern static ErrorCode EdsCreateFileStreamEx(string inFileName, FileCreateDisposition inCreateDisposition, FileAccess inDesiredAccess, out IntPtr outStream);
+
+ ///
+ /// Creates a stream from the memory buffer you prepared.
+ /// Unlike the buffer size of streams created by means of CreateMemoryStream, the buffer size you prepare
+ /// for streams created this way does not expand.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// -
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStreamFromPointer(IntPtr inUserBuffer, int inBufferSize, out IntPtr outStream);
+
+ ///
+ /// Creates a stream from the memory buffer you prepared.
+ /// Unlike the buffer size of streams created by means of CreateMemoryStream, the buffer size you prepare
+ /// for streams created this way does not expand.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// -
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStreamFromPointer(IntPtr inUserBuffer, long inBufferSize, out IntPtr outStream);
+
+ ///
+ /// Creates a stream from the memory buffer you prepared.
+ /// Unlike the buffer size of streams created by means of CreateMemoryStream, the buffer size you prepare for streams created this way does not expand.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// -
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStreamFromPointer(byte[] inUserBuffer, int inBufferSize, out IntPtr outStream);
+
+ ///
+ /// Creates a stream from the memory buffer you prepared.
+ /// Unlike the buffer size of streams created by means of CreateMemoryStream, the buffer size you prepare for streams created this way does not expand.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// -
+ /// The number of bytes of the memory to allocate.
+ /// The reference of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateMemoryStreamFromPointer(byte[] inUserBuffer, long inBufferSize, out IntPtr outStream);
+
+ ///
+ /// Creates a stream from an existing stream.
+ ///
+ /// The reference of the input stream.
+ /// The reference of the output stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateStream(IntPtr inStream, IntPtr outStreamRef);
+
+ ///
+ /// Gets the pointer to the start address of memory managed by the memory stream.
+ /// As the EDSDK automatically resizes the buffer, the memory stream provides you with the same access methods as for the file stream.
+ /// If access is attempted that is excessive with regard to the buffer size for the stream, data before the required buffer size is allocated is copied internally, and new writing occurs.
+ /// Thus, the buffer pointer might be switched on an unknown timing. Caution in use is therefore advised.
+ ///
+ /// Designate the memory stream for the pointer to retrieve.
+ /// If successful, returns the pointer to the buffer written in the memory stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPointer(IntPtr inStreamRef, out IntPtr outPointer);
+
+ ///
+ /// Reads data the size of inReadSize into the outBuffer buffer, starting at the current read or write position of the stream.
+ /// The size if data actually read can be designated in outReadSize.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to read.
+ /// Pointer to the user-supplied buffer that is to receive the data read from the stream.
+ /// The actually read number of bytes.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsRead(IntPtr inStreamRef, int inReadSize, IntPtr outBuffer, out int outReadSize);
+
+ ///
+ /// Reads data the size of inReadSize into the outBuffer buffer, starting at the current read or write position of the stream.
+ /// The size if data actually read can be designated in outReadSize.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to read.
+ /// Pointer to the user-supplied buffer that is to receive the data read from the stream.
+ /// The actually read number of bytes.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsRead(IntPtr inStreamRef, long inReadSize, IntPtr outBuffer, out long outReadSize);
+
+ ///
+ /// Writes data of a designated buffer to the current read or write position of the stream.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to write.
+ /// A pointer to the user-supplied buffer that contains the data to be written (in number of bytes)
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsWrite(IntPtr inStreamRef, int inWriteSize, IntPtr inBuffer, out int outWrittenSize);
+
+ ///
+ /// Writes data of a designated buffer to the current read or write position of the stream.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to write.
+ /// A pointer to the user-supplied buffer that contains the data to be written (in number of bytes)
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsWrite(IntPtr inStreamRef, long inWriteSize, IntPtr inBuffer, out long outWrittenSize);
+
+ ///
+ /// Moves the read or write position of the stream (that is, the file position indicator)
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// Number of bytes to move the pointer.
+ /// Pointer movement mode.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSeek(IntPtr inStreamRef, int inSeekOffset, SeekOrigin inSeekOrigin);
+
+ ///
+ /// Moves the read or write position of the stream (that is, the file position indicator)
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// Number of bytes to move the pointer.
+ /// Pointer movement mode.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSeek(IntPtr inStreamRef, long inSeekOffset, SeekOrigin inSeekOrigin);
+
+ ///
+ /// Gets the current read or write position of the stream (that is, the file position indicator)
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// The current stream pointer.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPosition(IntPtr inStreamRef, out int outPosition);
+
+ ///
+ /// Gets the current read or write position of the stream (that is, the file position indicator)
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// The current stream pointer.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetPosition(IntPtr inStreamRef, out long outPosition);
+
+ ///
+ /// Gets the stream size.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// The length of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetLength(IntPtr inStreamRef, out int outLength);
+
+ ///
+ /// Gets the stream size.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// The length of the stream.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetLength(IntPtr inStreamRef, out long outLength);
+
+ ///
+ /// Copies data from the copy source stream to the copy destination stream.
+ /// The read or write position of the data to copy is determined from the current file read or write position of the respective stream.
+ /// After this method is executed, the read or write position of the copy source and copy destination streams are moved
+ /// an amount corresponding to inWriteSize in the positive direction.
+ /// USE ONLY WITH SDK VERSION <3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to copy.
+ /// The reference of the stream or image.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCopyData(IntPtr inStreamRef, int inWriteSize, IntPtr outStreamRef);
+
+ ///
+ /// Copies data from the copy source stream to the copy destination stream.
+ /// The read or write position of the data to copy is determined from the current file read or write position of the respective stream.
+ /// After this method is executed, the read or write position of the copy source and copy destination streams are moved
+ /// an amount corresponding to inWriteSize in the positive direction.
+ /// USE ONLY WITH SDK VERSION >=3.4
+ ///
+ /// The reference of the stream or image.
+ /// The number of bytes to copy.
+ /// The reference of the stream or image.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCopyData(IntPtr inStreamRef, long inWriteSize, IntPtr outStreamRef);
+
+ #endregion
+
+ #region Image Handling
+
+ ///
+ /// Creates an image object from an image file.
+ /// Without modification, stream objects cannot be worked with as images.
+ /// Thus, when extracting images from image files, this method must be used to create image objects.
+ /// The image object created this way can be used to get image information
+ /// (such as height and width, number of components, and resolution), thumbnail image data, and the image data itself.
+ ///
+ /// The reference of the stream.
+ /// The reference of the image.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateImageRef(IntPtr inStreamRef, out IntPtr outImageRef);
+
+ ///
+ /// Gets image information from a designated image object.
+ /// Here, image information means the image width and height, number of color components, resolution, and effective image area.
+ ///
+ /// Designate the object which to get image information.
+ ///
+ /// Of the various image data items in the image file, designate the type of image data representing the information you want to get.
+ /// Designate the image as defined in the enum ImageSource.
+ ///
+ /// Stores the image information designated in inImageSource
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetImageInfo(IntPtr inImageRef, ImageSource inImageSource, out ImageInfo outImageInfo);
+
+ ///
+ /// Gets designated image data from an image file, in the form of a designated rectangle.
+ /// Returns uncompressed results for JPEGs and processed results in the designated pixel order (RGB, Top-down BGR, and so on) for RAW images.
+ /// Additionally, by designating the input/output rectangle, it is possible to get reduced, enlarged, or partial images.
+ /// However, because images corresponding to the designated output rectangle are always returned by the SDK, the SDK does not take the aspect ratio into account.
+ /// To maintain the aspect ratio, you must keep the aspect ratio in mind when designating the rectangle.
+ ///
+ /// Designate the image object for which to get the image data.
+ /// Designate the type of image data to get from the image file (thumbnail, preview, and so on). Designate values as defined in Enum ImageSource.
+ ///
+ /// Designate the output image type.
+ /// Because the output format of EdGetImage may only be RGB, only kTargetImageType_RGB or kTargetImageType_RGB16 can be designated.
+ /// However, image types exceeding the resolution of inImageSource cannot be designated.
+ ///
+ /// Designate the coordinates and size of the rectangle to be retrieved (processed) from the source image.
+ /// Designate the rectangle size for output.
+ /// Designate the memory or file stream for output of the image.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetImage(IntPtr inImageRef, ImageSource inImageSource, TargetImageType inImageType, Rectangle inSrcRect, Size inDstSize, IntPtr outStreamRef);
+
+ ///
+ /// Saves as a designated image type after RAW processing.
+ /// When saving with JPEG compression, the JPEG quality setting applies with respect to OptionRef.
+ ///
+ /// Designate the image object for which to produce the file.
+ /// Designate the image type to produce. Designate the following image types.
+ /// Designate saving options, such as JPEG image quality.
+ /// Specifies the output file stream. The memory stream cannot be specified here.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSaveImage(IntPtr inImageRef, SaveImageType inImageType, SaveImageSetting inSaveSetting, IntPtr outStreamRef);
+
+ ///
+ /// Switches a setting on and off for creation of an image cache in the SDK for a designated image object during extraction (processing) of the image data.
+ ///
+ /// The reference of the image.
+ /// If cache image data or not. If set to false, the cached image data will be released.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCacheImage(IntPtr inImageRef, bool inUseCache);
+
+ ///
+ /// Incorporates image object property changes (effected by means of SetPropertyData) in the stream.
+ ///
+ /// The reference of the image.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsReflectImageProperty(IntPtr inImageRef);
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Registers a callback function for when a camera is detected.
+ ///
+ /// Pointer to a callback function called when a camera is connected physically.
+ /// Specifies an application-defined value to be sent to the callback function pointed to by CallBack parameter.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetCameraAddedHandler(SDKCameraAddedHandler inCameraAddedHandler, IntPtr inContext);
+
+ ///
+ /// Registers a callback function for receiving status change notification events for property-related camera evens.
+ ///
+ /// Designate the camera object.
+ /// Designate one or all events to be supplemented.
+ /// Designate the pointer to the callback function for receiving property-related camera events.
+ /// Designate application information to be passed by mens of the callback funcion.Any data needed for your application can be passed.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetPropertyEventHandler(IntPtr inCameraRef, PropertyEventID inEvent, SDKPropertyEventHandler inPropertyEventHandler, IntPtr inContext);
+
+ ///
+ /// Registers a callback function for receiving status change notification events for objects on a remote camera.
+ /// Here, object means columns representation memory cards, files and directories, and shot images stored in memory, in particular.
+ ///
+ /// Designate the camera object.
+ /// Designate one or all events to be supplemented.
+ /// Designate the pointer to the callback function for receiving object-related camera events.
+ /// Passes inContext without modification, as designated as an SetObjectEventHandler argument.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetObjectEventHandler(IntPtr inCameraRef, ObjectEventID inEvent, SDKObjectEventHandler inObjectEventHandler, IntPtr inContext);
+
+ ///
+ /// Registers a callback function for receiving status change notification events for property states on a camera.
+ ///
+ /// Designate the camera object.
+ /// Designate one or all events to be supplemented.
+ /// Designate the pointer to the callback function for receiving events related to camera object states.
+ /// Designate application information to be passed by means of the callback function. Any data needed for the application can be passed.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetCameraStateEventHandler(IntPtr inCameraRef, StateEventID inEvent, SDKStateEventHandler inStateEventHandler, IntPtr inContext);
+
+ ///
+ /// Register a progress callback function.
+ /// An event is received as notification of progress during processing that takes a relatively long time, such as downloading files from a remote camera.
+ /// If you register the callback function, the EDSDK calls the callback function during execution or on completion of the following APIs.
+ /// This timing can be used in updating on-screen progress bars, for example.
+ ///
+ /// The reference of the stream or image.
+ /// Pointer to the progress callback function.
+ /// The option about progress is specified.
+ ///
+ /// Application information, passed in the argument when the callback function is called.
+ /// Any information required for the program may be added.
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsSetProgressCallback(IntPtr inRef, SDKProgressCallback inProgressFunc, ProgressOption inProgressOption, IntPtr inContext);
+
+ ///
+ /// This function acquires an event.
+ /// In console application, please call this function regularly to acquire
+ /// the event from a camera.
+ ///
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetEvent();
+
+ #endregion
+
+ #region Evf Image
+
+ ///
+ /// Creates an object used to get the live view image data set.
+ ///
+ /// The stream reference which opened to get EVF JPEG image.
+ /// The EVFData reference.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsCreateEvfImageRef(IntPtr inStreamRef, out IntPtr outEvfImageRef);
+
+ ///
+ /// Downloads the live view image data set for a camera currently in live view mode.
+ /// Live view can be started by using the property ID: PropertyID_Evf_OutputDevice and
+ /// data:OutputDevice_PC to call SetPropertyData.
+ /// In addition to image data, information such as zoom, focus position, and histogram data
+ /// is included in the image data set. Image data is saved in a stream maintained by EvfImageRef.
+ /// GetPropertyData can be used to get information such as the zoom, focus position, etc.
+ /// Although the information of the zoom and focus position can be obtained from EvfImageRef,
+ /// settings are applied to CameraRef.
+ ///
+ /// The camera reference.
+ /// The EVFData reference.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsDownloadEvfImage(IntPtr inCameraRef, IntPtr outEvfImageRef);
+
+ #endregion
+
+ #region Misc
+
+ ///
+ /// Gets camera list objects.
+ ///
+ /// Pointer to the camera-list.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetCameraList(out IntPtr outCameraListRef);
+
+ ///
+ /// Gets device information, such as the device name.
+ /// Because device information of remote cameras is stored on the host computer, this method can be called before the session with the camera is opened.
+ ///
+ /// The reference of the camera.
+ /// Information as device of camera.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetDeviceInfo(IntPtr inCameraRef, out DeviceInfo outDeviceInfo);
+
+ ///
+ /// Increments the reference counter of existing objects.
+ ///
+ /// The reference for the item
+ /// The number of references for this pointer or 0xFFFFFFFF for an error
+ [DllImport(DllPath)]
+ public extern static int EdsRetain(IntPtr inRef);
+
+ ///
+ /// Decrements the reference counter of an object.
+ /// When the reference counter reaches 0, the object is release.
+ ///
+ /// The reference of the item.
+ /// The number of references for this pointer or 0xFFFFFFFF for an error
+ [DllImport(DllPath)]
+ public extern static int EdsRelease(IntPtr inRef);
+
+ ///
+ /// Gets the number of child objects of the designated object.
+ /// Example: Number of files in a directory
+ ///
+ /// The reference of the list
+ /// Number of elements in this list.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetChildCount(IntPtr inRef, out int outCount);
+
+ ///
+ /// Gets an indexed child object of the designated object.
+ ///
+ /// The reference of the item
+ /// The index that is passes in (zero based)
+ /// The pointer which receives reference of the specific index.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetChildAtIndex(IntPtr inRef, int inIndex, out IntPtr outRef);
+
+ ///
+ /// Gets the parent object of the designated object.
+ ///
+ /// The reference of the item.
+ /// The pointer which receives reference.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ public extern static ErrorCode EdsGetParent(IntPtr inRef, out IntPtr outParentRef);
+
+ #endregion
+
+ #region Helper Methods
+
+ ///
+ /// Gets information about the directory or file object on the memory card (volume) in a remote camera.
+ /// This method works regardless of the used SDK version.
+ ///
+ /// The reference of the directory item.
+ /// Information of the directory item.
+ /// Any of the SDK errors
+ public static ErrorCode GetDirectoryItemInfo(IntPtr inDirItemRef, out DirectoryItemInfo outDirItemInfo)
+ {
+ if (IsVerGE34) { return EdsGetDirectoryItemInfo(inDirItemRef, out outDirItemInfo); }
+ else
+ {
+ DirectoryItemInfo_3_4 tmpValue;
+ ErrorCode err = EdsGetDirectoryItemInfo(inDirItemRef, out tmpValue);
+ if (err == ErrorCode.OK)
+ {
+ outDirItemInfo = tmpValue.ToCurrent();
+ return err;
+ }
+
+ outDirItemInfo = default(DirectoryItemInfo);
+ return err;
+ }
+ }
+
+ ///
+ /// Gets information about the directory or file object on the memory card (volume) in a remote camera.
+ ///
+ ///
+ /// The reference of the directory item.
+ /// Information of the directory item.
+ /// Any of the SDK errors
+ [DllImport(DllPath)]
+ private extern static ErrorCode EdsGetDirectoryItemInfo(IntPtr inDirItemRef, out DirectoryItemInfo_3_4 outDirItemInfo);
+
+ #endregion
+
+ #region GetPropertyData Wrapper
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ /// This method takes care of differences between SDK versions.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// The type of a struct. Must be on of the types described in the enum
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out T outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ outPropertyData = default(T);
+
+ if (outPropertyData is PictureStyleDesc)
+ {
+ PictureStyleDesc tmpValue;
+ err = GetPropertyData(inRef, inPropertyID, inParam, out tmpValue);
+ if (err == ErrorCode.OK) outPropertyData = (T)(object)tmpValue;
+ }
+ else { err = GetPropertyDataSub(inRef, inPropertyID, inParam, out outPropertyData); }
+
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// The type of a struct. Must be on of the types described in the enum
+ /// Any of the SDK errors
+ private static ErrorCode GetPropertyDataSub(IntPtr inRef, PropertyID inPropertyID, int inParam, out T outPropertyData)
+ {
+ IntPtr ptr = IntPtr.Zero;
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ outPropertyData = default(T);
+
+ try
+ {
+ DataType dt;
+ int size;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out dt, out size);
+
+ if (err == ErrorCode.OK)
+ {
+ ptr = Marshal.AllocHGlobal(size);
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, ptr);
+
+ if (err == ErrorCode.OK) outPropertyData = (T)Marshal.PtrToStructure(ptr, typeof(T));
+ }
+ }
+ finally { if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr); }
+
+ return err;
+ }
+
+ #region Primitive Types
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out bool outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(bool));
+ bool val;
+ unsafe
+ {
+ bool* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out byte outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(byte));
+ byte val;
+ unsafe
+ {
+ byte* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out short outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(short));
+ short val;
+ unsafe
+ {
+ short* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ [CLSCompliant(false)]
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out ushort outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(ushort));
+ ushort val;
+ unsafe
+ {
+ ushort* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ [CLSCompliant(false)]
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out uint outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(uint));
+ uint val;
+ unsafe
+ {
+ uint* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out int outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(int));
+ int val;
+ unsafe
+ {
+ int* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out string outPropertyData)
+ {
+ IntPtr ptr = IntPtr.Zero;
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ outPropertyData = string.Empty;
+ try
+ {
+ DataType dt;
+ int size;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out dt, out size);
+
+ if (err == ErrorCode.OK)
+ {
+ ptr = Marshal.AllocHGlobal(size);
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, ptr);
+
+ if (err == ErrorCode.OK) outPropertyData = Marshal.PtrToStringAnsi(ptr);
+ }
+ }
+ finally { if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr); }
+ return err;
+ }
+
+ #endregion
+
+ #region Arrays
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out bool[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(bool));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new bool[propsize / tpsize];
+ unsafe
+ {
+ fixed (bool* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new bool[0];
+ }
+ else outPropertyData = new bool[0];
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out short[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(short));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new short[propsize / tpsize];
+ unsafe
+ {
+ fixed (short* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new short[0];
+ }
+ else outPropertyData = new short[0];
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out int[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(int));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new int[propsize / tpsize];
+ unsafe
+ {
+ fixed (int* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new int[0];
+ }
+ else outPropertyData = new int[0];
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out byte[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(byte));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new byte[propsize / tpsize];
+ unsafe
+ {
+ fixed (byte* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new byte[0];
+ }
+ else outPropertyData = new byte[0];
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ [CLSCompliant(false)]
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out uint[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(uint));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new uint[propsize / tpsize];
+ unsafe
+ {
+ fixed (uint* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new uint[0];
+ }
+ else outPropertyData = new uint[0];
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out Rational[] outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int tpsize = Marshal.SizeOf(typeof(Rational));
+ int propsize;
+ DataType proptype;
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out proptype, out propsize);
+ if (err == ErrorCode.OK)
+ {
+ var data = new Rational[propsize / tpsize];
+ unsafe
+ {
+ fixed (Rational* dataP = data)
+ {
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, propsize, (IntPtr)dataP);
+ }
+ }
+ if (err == ErrorCode.OK) outPropertyData = data;
+ else outPropertyData = new Rational[0];
+ }
+ else outPropertyData = new Rational[0];
+ return err;
+ }
+
+ #endregion
+
+ #region Structs
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out Time outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(Time));
+ Time val;
+ unsafe
+ {
+ Time* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out FocusInfo outPropertyData)
+ {
+ IntPtr ptr = IntPtr.Zero;
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ try
+ {
+ int size = Marshal.SizeOf(typeof(FocusInfo));
+ ptr = Marshal.AllocHGlobal(size);
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, ptr);
+
+ outPropertyData = (FocusInfo)Marshal.PtrToStructure(ptr, typeof(FocusInfo));
+ }
+ finally { if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr); }
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out FocusPoint outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(FocusPoint));
+ FocusPoint val;
+ unsafe
+ {
+ FocusPoint* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out Size outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(Size));
+ Size val;
+ unsafe
+ {
+ Size* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out Rectangle outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(Rectangle));
+ Rectangle val;
+ unsafe
+ {
+ Rectangle* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out Point outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(Point));
+ Point val;
+ unsafe
+ {
+ Point* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out MyMenuItems outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ int size = Marshal.SizeOf(typeof(MyMenuItems));
+ MyMenuItems val;
+ unsafe
+ {
+ MyMenuItems* ptr = &val;
+ err = EdsGetPropertyData(inRef, inPropertyID, inParam, size, (IntPtr)ptr);
+ }
+ outPropertyData = val;
+ return err;
+ }
+
+ ///
+ /// Gets property information from the object designated in inRef.
+ ///
+ /// The reference of the item.
+ /// The property ID.
+ /// Additional information of property. Used in order to specify an index in case there are two or more values over the same ID.
+ /// The value of the property.
+ /// Any of the SDK errors
+ public static ErrorCode GetPropertyData(IntPtr inRef, PropertyID inPropertyID, int inParam, out PictureStyleDesc outPropertyData)
+ {
+ ErrorCode err = ErrorCode.INTERNAL_ERROR;
+ DataType dt;
+ int size;
+ outPropertyData = default(PictureStyleDesc);
+
+ err = EdsGetPropertySize(inRef, inPropertyID, inParam, out dt, out size);
+
+ if (err == ErrorCode.OK)
+ {
+ if (size == Marshal.SizeOf(typeof(PictureStyleDesc)))
+ {
+ return GetPropertyDataSub(inRef, inPropertyID, inParam, out outPropertyData);
+ }
+ else if (size == Marshal.SizeOf(typeof(PictureStyleDesc_3_2)))
+ {
+ PictureStyleDesc_3_2 tmpValue;
+ err = GetPropertyDataSub(inRef, inPropertyID, inParam, out tmpValue);
+ if (err == ErrorCode.OK)
+ {
+ outPropertyData = tmpValue.ToCurrent();
+ return err;
+ }
+ }
+ else throw new InvalidOperationException("Cannot find correct struct size");
+ }
+
+ return err;
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/src/CamBooth/EDSDKLib/SDK/SDKStructs.cs b/src/CamBooth/EDSDKLib/SDK/SDKStructs.cs
new file mode 100644
index 0000000..6d27569
--- /dev/null
+++ b/src/CamBooth/EDSDKLib/SDK/SDKStructs.cs
@@ -0,0 +1,1622 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace EOSDigital.SDK
+{
+ ///
+ /// Point
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Point
+ {
+ ///
+ /// X Coordinate
+ ///
+ public int X;
+ ///
+ /// Y Coordinate
+ ///
+ public int Y;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// X Coordinate
+ /// Y Coordinate
+ public Point(int X, int Y)
+ {
+ this.X = X;
+ this.Y = Y;
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Point x, Point y)
+ {
+ return x.X == y.X && x.Y == y.Y;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Point x, Point y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Point && this == (Point)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ X.GetHashCode();
+ hash *= 16777619 ^ Y.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
+ public override string ToString()
+ {
+ return string.Concat(X, ";", Y);
+ }
+ }
+
+ ///
+ /// Size
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Size
+ {
+ ///
+ /// Width
+ ///
+ public int Width;
+ ///
+ /// Height
+ ///
+ public int Height;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ public Size(int Width, int Height)
+ {
+ this.Width = Width;
+ this.Height = Height;
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Size x, Size y)
+ {
+ return x.Width == y.Width && x.Height == y.Height;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Size x, Size y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Size && this == (Size)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Width.GetHashCode();
+ hash *= 16777619 ^ Height.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
+ public override string ToString()
+ {
+ return string.Concat(Width, ";", Height);
+ }
+ }
+
+ ///
+ /// Rectangle
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Rectangle
+ {
+ ///
+ /// X Coordinate
+ ///
+ public int X;
+ ///
+ /// Y Coordinate
+ ///
+ public int Y;
+ ///
+ /// Width of the rectangle
+ ///
+ public int Width;
+ ///
+ /// Height of the rectangle
+ ///
+ public int Height;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Width of the rectangle
+ /// Height of the rectangle
+ public Rectangle(int Width, int Height)
+ : this(0, 0, Width, Height)
+ { }
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// X Coordinate
+ /// Y Coordinate
+ /// Width of the rectangle
+ /// Height of the rectangle
+ public Rectangle(int X, int Y, int Width, int Height)
+ {
+ this.X = X;
+ this.Y = Y;
+ this.Width = Width;
+ this.Height = Height;
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Rectangle x, Rectangle y)
+ {
+ return x.X == y.X && x.Y == y.Y && x.Width == y.Width && x.Height == y.Height;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Rectangle x, Rectangle y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Rectangle && this == (Rectangle)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ X.GetHashCode();
+ hash *= 16777619 ^ Y.GetHashCode();
+ hash *= 16777619 ^ Width.GetHashCode();
+ hash *= 16777619 ^ Height.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
+ public override string ToString()
+ {
+ return string.Concat(X, ";", Y, ";", Width, ";", Height);
+ }
+ }
+
+ ///
+ /// Rational
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Rational
+ {
+ ///
+ /// Numerator of the rational number
+ ///
+ public int Numerator;
+ ///
+ /// Denominator of the rational number
+ ///
+ public int Denominator;
+
+
+ ///
+ /// Calculates the value as double
+ ///
+ /// The given Rational value
+ /// The Rational as double
+ public static implicit operator double(Rational val)
+ {
+ return val.Numerator / (double)val.Denominator;
+ }
+
+ ///
+ /// Calculates the value as decimal
+ ///
+ /// The given Rational value
+ /// The Rational as decimal
+ public static implicit operator decimal(Rational val)
+ {
+ return val.Numerator / (decimal)val.Denominator;
+ }
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Rational x, Rational y)
+ {
+ return x.Numerator == y.Numerator && x.Denominator == y.Denominator;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Rational x, Rational y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Rational && this == (Rational)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Numerator.GetHashCode();
+ hash *= 16777619 ^ Denominator.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
+ public override string ToString()
+ {
+ return Numerator + "/" + Denominator;
+ }
+ }
+
+ ///
+ /// Time
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Time
+ {
+ ///
+ /// Year component
+ ///
+ public int Year;
+ ///
+ /// Month component
+ ///
+ public int Month;
+ ///
+ /// Day component
+ ///
+ public int Day;
+ ///
+ /// Hour component
+ ///
+ public int Hour;
+ ///
+ /// Minute component
+ ///
+ public int Minute;
+ ///
+ /// Second component
+ ///
+ public int Second;
+ ///
+ /// Milliseconds component
+ ///
+ public int Milliseconds;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Year component
+ /// Month component
+ /// Day component
+ public Time(int Year, int Month, int Day)
+ : this(Year, Month, Day, 0, 0, 0, 0)
+ { }
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Year component
+ /// Month component
+ /// Day component
+ /// Hour component
+ public Time(int Year, int Month, int Day, int Hour)
+ : this(Year, Month, Day, Hour, 0, 0, 0)
+ { }
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Year component
+ /// Month component
+ /// Day component
+ /// Hour component
+ /// Minute component
+ public Time(int Year, int Month, int Day, int Hour, int Minute)
+ : this(Year, Month, Day, Hour, Minute, 0, 0)
+ { }
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Year component
+ /// Month component
+ /// Day component
+ /// Hour component
+ /// Minute component
+ /// Second component
+ public Time(int Year, int Month, int Day, int Hour, int Minute, int Second)
+ : this(Year, Month, Day, Hour, Minute, Second, 0)
+ { }
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Year component
+ /// Month component
+ /// Day component
+ /// Hour component
+ /// Minute component
+ /// Second component
+ /// Milliseconds component
+ public Time(int Year, int Month, int Day, int Hour, int Minute, int Second, int Milliseconds)
+ {
+ this.Year = Year;
+ this.Month = Month;
+ this.Day = Day;
+ this.Hour = Hour;
+ this.Minute = Minute;
+ this.Second = Second;
+ this.Milliseconds = Milliseconds;
+ }
+
+
+ ///
+ /// Implicitly converts to
+ /// ///
+ /// The to convert
+ /// The
+ public static implicit operator DateTime(Time t)
+ {
+ return new DateTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second, t.Milliseconds);
+ }
+
+ ///
+ /// Implicitly converts to
+ ///
+ /// The to convert
+ /// The
+ public static implicit operator Time(DateTime t)
+ {
+ return new Time(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second, t.Millisecond);
+ }
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Time x, Time y)
+ {
+ return x.Year == y.Year && x.Month == y.Month && x.Day == y.Day && x.Hour == y.Hour
+ && x.Minute == y.Minute && x.Second == y.Second && x.Milliseconds == y.Milliseconds;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Time x, Time y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Time && this == (Time)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Year.GetHashCode();
+ hash *= 16777619 ^ Month.GetHashCode();
+ hash *= 16777619 ^ Day.GetHashCode();
+ hash *= 16777619 ^ Hour.GetHashCode();
+ hash *= 16777619 ^ Minute.GetHashCode();
+ hash *= 16777619 ^ Second.GetHashCode();
+ hash *= 16777619 ^ Milliseconds.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
+ public override string ToString()
+ {
+ return ((DateTime)this).ToString();
+ }
+ }
+
+ ///
+ /// Device Info
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DeviceInfo
+ {
+ ///
+ /// Name of port
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CanonSDK.MAX_NAME)]
+ public string PortName;
+ ///
+ /// Name of device
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CanonSDK.MAX_NAME)]
+ public string DeviceDescription;
+ ///
+ /// Device Sub-type
+ ///
+ public DeviceSubType DeviceSubType;
+ private uint Reserved;
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(DeviceInfo x, DeviceInfo y)
+ {
+ return x.PortName == y.PortName && x.DeviceDescription == y.DeviceDescription && x.DeviceSubType == y.DeviceSubType;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(DeviceInfo x, DeviceInfo y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is DeviceInfo && this == (DeviceInfo)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ PortName.GetHashCode();
+ hash *= 16777619 ^ DeviceDescription.GetHashCode();
+ hash *= 16777619 ^ DeviceSubType.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// Volume Info
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VolumeInfo
+ {
+ ///
+ /// Type of storage
+ ///
+ public int StorageType;
+ ///
+ /// Accessibility
+ ///
+ public FileAccess Access;
+ ///
+ /// Maximum capacity
+ ///
+ public long MaxCapacity;
+ ///
+ /// Free space on volume in bytes
+ ///
+ public long FreeSpaceInBytes;
+ ///
+ /// Label/name of the volume
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CanonSDK.MAX_NAME)]
+ public string VolumeLabel;
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(VolumeInfo x, VolumeInfo y)
+ {
+ return x.StorageType == y.StorageType && x.Access == y.Access && x.MaxCapacity == y.MaxCapacity
+ && x.FreeSpaceInBytes == y.FreeSpaceInBytes && x.VolumeLabel == y.VolumeLabel;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(VolumeInfo x, VolumeInfo y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is VolumeInfo && this == (VolumeInfo)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ StorageType.GetHashCode();
+ hash *= 16777619 ^ Access.GetHashCode();
+ hash *= 16777619 ^ MaxCapacity.GetHashCode();
+ hash *= 16777619 ^ FreeSpaceInBytes.GetHashCode();
+ hash *= 16777619 ^ VolumeLabel.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// DirectoryItem Info
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DirectoryItemInfo
+ {
+ ///
+ /// Size of directory item
+ ///
+ public int Size
+ {
+ get { return (int)Size64; }
+ }
+
+ ///
+ /// Size of directory item (as long)
+ ///
+ public long Size64;
+ ///
+ /// Marker if it's a folder or a file
+ ///
+ public bool IsFolder;
+ ///
+ /// Group ID
+ ///
+ public int GroupID;
+ ///
+ /// Option
+ ///
+ public int Option;
+ ///
+ /// File name
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CanonSDK.MAX_NAME)]
+ public string FileName;
+ ///
+ /// Format
+ ///
+ public TargetImageType Format;
+ ///
+ /// Date time
+ ///
+ public int DateTime;
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(DirectoryItemInfo x, DirectoryItemInfo y)
+ {
+ return x.Size == y.Size && x.IsFolder == y.IsFolder && x.GroupID == y.GroupID && x.Option == y.Option
+ && x.FileName == y.FileName && x.Format == y.Format && x.DateTime == y.DateTime;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(DirectoryItemInfo x, DirectoryItemInfo y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is DirectoryItemInfo && this == (DirectoryItemInfo)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Size.GetHashCode();
+ hash *= 16777619 ^ IsFolder.GetHashCode();
+ hash *= 16777619 ^ GroupID.GetHashCode();
+ hash *= 16777619 ^ Option.GetHashCode();
+ hash *= 16777619 ^ FileName.GetHashCode();
+ hash *= 16777619 ^ Format.GetHashCode();
+ hash *= 16777619 ^ DateTime.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// DirectoryItemInfo struct for SDK versions <3.4
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct DirectoryItemInfo_3_4
+ {
+ public int Size;
+ public bool IsFolder;
+ public int GroupID;
+ public int Option;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CanonSDK.MAX_NAME)]
+ public string FileName;
+ public TargetImageType Format;
+ public int DateTime;
+
+ public DirectoryItemInfo ToCurrent()
+ {
+ return new DirectoryItemInfo
+ {
+ Size64 = Size,
+ IsFolder = IsFolder,
+ GroupID = GroupID,
+ Option = Option,
+ FileName = FileName,
+ DateTime = DateTime,
+ };
+ }
+ }
+
+ ///
+ /// Image Info
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ImageInfo
+ {
+ ///
+ /// Width of image
+ ///
+ public int Width;
+ ///
+ /// Height of image
+ ///
+ public int Height;
+ ///
+ /// Number of channels
+ ///
+ public int NumOfComponents;
+ ///
+ /// Bitdepth of channels
+ ///
+ public int ComponentDepth;
+ ///
+ /// Effective size of image
+ ///
+ public Rectangle EffectiveRect;
+ private uint Reserved1;
+ private uint Reserved2;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(ImageInfo x, ImageInfo y)
+ {
+ return x.Width == y.Width && x.Height == y.Height && x.NumOfComponents == y.NumOfComponents
+ && x.ComponentDepth == y.ComponentDepth && x.EffectiveRect == y.EffectiveRect;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(ImageInfo x, ImageInfo y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is ImageInfo && this == (ImageInfo)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Width.GetHashCode();
+ hash *= 16777619 ^ Height.GetHashCode();
+ hash *= 16777619 ^ NumOfComponents.GetHashCode();
+ hash *= 16777619 ^ ComponentDepth.GetHashCode();
+ hash *= 16777619 ^ EffectiveRect.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// SaveImage Setting
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SaveImageSetting
+ {
+ ///
+ /// Quality of Jpeg file (1-10)
+ ///
+ public int JPEGQuality;
+ ///
+ /// Pointer to ICC profile stream
+ ///
+ public IntPtr ICCProfileStream;
+ private uint Reserved;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(SaveImageSetting x, SaveImageSetting y)
+ {
+ return x.JPEGQuality == y.JPEGQuality && x.ICCProfileStream == y.ICCProfileStream;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(SaveImageSetting x, SaveImageSetting y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is SaveImageSetting && this == (SaveImageSetting)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ JPEGQuality.GetHashCode();
+ hash *= 16777619 ^ ICCProfileStream.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// Property Description
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PropertyDesc
+ {
+ ///
+ /// Form
+ ///
+ public int Form;
+ ///
+ /// Accessibility
+ ///
+ public int Access;
+ ///
+ /// Number of elements
+ ///
+ public int NumElements;
+ ///
+ /// Array of all elements
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
+ public int[] PropDesc;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(PropertyDesc x, PropertyDesc y)
+ {
+ return x.Form == y.Form && x.Access == y.Access && x.NumElements == y.NumElements && x.PropDesc.SequenceEqual(y.PropDesc);
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(PropertyDesc x, PropertyDesc y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is PropertyDesc && this == (PropertyDesc)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Form.GetHashCode();
+ hash *= 16777619 ^ Access.GetHashCode();
+ hash *= 16777619 ^ NumElements.GetHashCode();
+ hash *= 16777619 ^ PropDesc.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// Picture Style Description
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PictureStyleDesc
+ {
+ ///
+ /// Contrast; Range: -4 to 4
+ ///
+ public int Contrast;
+ ///
+ /// Sharpness; Range: 0 to 7
+ ///
+ public int Sharpness;
+ ///
+ /// Saturation; Range: -4 to 4
+ ///
+ public int Saturation;
+ ///
+ /// ColorTone; Range: -4 to 4
+ ///
+ public int ColorTone;
+ ///
+ /// Filter Effect
+ ///
+ public FilterEffect FilterEffect;
+ ///
+ /// Toning Effect
+ ///
+ public ToningEffect ToningEffect;
+ ///
+ /// Sharp Fineness
+ ///
+ public int SharpFineness;
+ ///
+ /// Sharp Threshold
+ ///
+ public int SharpThreshold;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Range: -4 to 4
+ /// Range: 0 to 7
+ /// Range: -4 to 4
+ /// Range: -4 to 4
+ /// Filter Effect
+ /// Toning Effect
+ public PictureStyleDesc(int Contrast, int Sharpness, int Saturation, int ColorTone, int FilterEffect, int ToningEffect)
+ {
+ this.Contrast = Math.Min(4, Math.Max(-4, Contrast));
+ this.Sharpness = Math.Min(7, Math.Max(0, Sharpness));
+ this.Saturation = Math.Min(4, Math.Max(-4, Saturation));
+ this.ColorTone = Math.Min(4, Math.Max(-4, ColorTone));
+ this.FilterEffect = (FilterEffect)FilterEffect;
+ this.ToningEffect = (ToningEffect)ToningEffect;
+ SharpFineness = 0;
+ SharpThreshold = 0;
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(PictureStyleDesc x, PictureStyleDesc y)
+ {
+ return x.Contrast == y.Contrast && x.Sharpness == y.Sharpness && x.Saturation == y.Saturation && x.ColorTone == y.ColorTone
+ && x.FilterEffect == y.FilterEffect && x.ToningEffect == y.ToningEffect;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(PictureStyleDesc x, PictureStyleDesc y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is PictureStyleDesc && this == (PictureStyleDesc)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Contrast.GetHashCode();
+ hash *= 16777619 ^ Sharpness.GetHashCode();
+ hash *= 16777619 ^ Saturation.GetHashCode();
+ hash *= 16777619 ^ ColorTone.GetHashCode();
+ hash *= 16777619 ^ FilterEffect.GetHashCode();
+ hash *= 16777619 ^ ToningEffect.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// PictureStyleDesc struct for SDK versions <3.2
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PictureStyleDesc_3_2
+ {
+ public int Contrast;
+ public int Sharpness;
+ public int Saturation;
+ public int ColorTone;
+ public FilterEffect FilterEffect;
+ public ToningEffect ToningEffect;
+
+ public PictureStyleDesc ToCurrent()
+ {
+ return new PictureStyleDesc
+ {
+ Contrast = Contrast,
+ Sharpness = Sharpness,
+ Saturation = Saturation,
+ ColorTone = ColorTone,
+ FilterEffect = FilterEffect,
+ ToningEffect = ToningEffect,
+ };
+ }
+ }
+
+ ///
+ /// Focus Point
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FocusPoint
+ {
+ ///
+ /// Invalid AF frame: 0
+ /// Valid AF frame: 1
+ /// Note: There are as many valid AF frames as the number in
+ /// FrameNumber. Usually, AF frames are recorded consecutively, starting with 0.
+ /// Note: AF frame coordinates and the array number for storage vary by model.
+ ///
+ public int Valid;
+ ///
+ /// Selected AF frame: 0
+ /// Unselected AF frame: 1
+ ///
+ public int Selected;
+ ///
+ /// In focus: 1
+ /// Out of focus: 0
+ ///
+ public int JustFocus;
+ ///
+ /// Upper-left and lower-right coordinates of the AF frame
+ ///
+ public Rectangle Rectangle;
+ private uint Reserved;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(FocusPoint x, FocusPoint y)
+ {
+ return x.Valid == y.Valid && x.Selected == y.Selected && x.JustFocus == y.JustFocus && x.Rectangle == y.Rectangle;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(FocusPoint x, FocusPoint y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is FocusPoint && this == (FocusPoint)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Valid.GetHashCode();
+ hash *= 16777619 ^ Selected.GetHashCode();
+ hash *= 16777619 ^ JustFocus.GetHashCode();
+ hash *= 16777619 ^ Rectangle.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// Focus Info
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FocusInfo
+ {
+ ///
+ /// The upper-left coordinates of the image, as well as the width and height
+ ///
+ public Rectangle ImageRectangle;
+ ///
+ /// AF frame number
+ ///
+ public int PointNumber;
+ ///
+ /// Detailed information about focus points
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
+ public FocusPoint[] FocusPoints;
+ ///
+ /// Execute Mode
+ ///
+ public int ExecuteMode;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(FocusInfo x, FocusInfo y)
+ {
+ return x.ImageRectangle == y.ImageRectangle && x.PointNumber == y.PointNumber
+ && x.FocusPoints.SequenceEqual(y.FocusPoints) && x.ExecuteMode == y.ExecuteMode;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(FocusInfo x, FocusInfo y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is FocusInfo && this == (FocusInfo)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ ImageRectangle.GetHashCode();
+ hash *= 16777619 ^ PointNumber.GetHashCode();
+ hash *= 16777619 ^ FocusPoints.GetHashCode();
+ hash *= 16777619 ^ ExecuteMode.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// User WhiteBalance (PC set1,2,3); User ToneCurve; User PictureStyle dataset
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UsersetData
+ {
+ ///
+ /// Marker if data is valid
+ ///
+ public int Valid;
+ ///
+ /// Size of data
+ ///
+ public int DataSize;
+ ///
+ /// Caption
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string Caption;
+ ///
+ /// Data
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
+ public byte[] Data;
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(UsersetData x, UsersetData y)
+ {
+ return x.Valid == y.Valid && x.DataSize == y.DataSize && x.Caption == y.Caption && x.Data.SequenceEqual(y.Data);
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(UsersetData x, UsersetData y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is UsersetData && this == (UsersetData)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ Valid.GetHashCode();
+ hash *= 16777619 ^ DataSize.GetHashCode();
+ hash *= 16777619 ^ Caption.GetHashCode();
+ hash *= 16777619 ^ Data.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// Capacity
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 2)]
+ public struct Capacity
+ {
+ ///
+ /// Number of free clusters on the HD
+ ///
+ public int NumberOfFreeClusters;
+ ///
+ /// Bytes per HD sector
+ ///
+ public int BytesPerSector;
+ ///
+ /// Reset flag
+ ///
+ public bool Reset;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Bytes per HD sector
+ /// Number of free clusters on the HD
+ ///
+ public Capacity(int NumberOfFreeClusters, int BytesPerSector, bool Reset)
+ {
+ this.NumberOfFreeClusters = NumberOfFreeClusters;
+ this.BytesPerSector = BytesPerSector;
+ this.Reset = Reset;
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(Capacity x, Capacity y)
+ {
+ return x.NumberOfFreeClusters == y.NumberOfFreeClusters && x.BytesPerSector == y.BytesPerSector && x.Reset == y.Reset;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(Capacity x, Capacity y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Capacity && this == (Capacity)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ NumberOfFreeClusters.GetHashCode();
+ hash *= 16777619 ^ BytesPerSector.GetHashCode();
+ hash *= 16777619 ^ Reset.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ ///
+ /// MyMenu Items
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct MyMenuItems
+ {
+ ///
+ /// Menu Item 1
+ ///
+ public MyMenuID MenuItem1;
+ ///
+ /// Menu Item 2
+ ///
+ public MyMenuID MenuItem2;
+ ///
+ /// Menu Item 3
+ ///
+ public MyMenuID MenuItem3;
+ ///
+ /// Menu Item 4
+ ///
+ public MyMenuID MenuItem4;
+ ///
+ /// Menu Item 5
+ ///
+ public MyMenuID MenuItem5;
+ ///
+ /// Menu Item 6
+ ///
+ public MyMenuID MenuItem6;
+
+ ///
+ /// Creates a new instance of the struct
+ ///
+ /// Array of items (max length is 6)
+ /// The array of given items is null
+ public MyMenuItems(params MyMenuID[] items)
+ {
+ if (items == null) throw new ArgumentNullException(nameof(items));
+
+ MenuItem1 = MenuItem2 = MenuItem3 = MenuItem4 = MenuItem5 = MenuItem6 = MyMenuID.NotSet;
+
+ if (items.Length > 0) MenuItem1 = items[0];
+ if (items.Length > 1) MenuItem2 = items[1];
+ if (items.Length > 2) MenuItem3 = items[2];
+ if (items.Length > 3) MenuItem4 = items[3];
+ if (items.Length > 4) MenuItem5 = items[4];
+ if (items.Length > 5) MenuItem6 = items[5];
+ }
+
+
+ ///
+ /// Determines whether the specified s are equal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are equal; otherwise, false
+ public static bool operator ==(MyMenuItems x, MyMenuItems y)
+ {
+ return x.MenuItem1 == y.MenuItem1
+ && x.MenuItem2 == y.MenuItem2
+ && x.MenuItem3 == y.MenuItem3
+ && x.MenuItem4 == y.MenuItem4
+ && x.MenuItem5 == y.MenuItem5
+ && x.MenuItem6 == y.MenuItem6;
+ }
+
+ ///
+ /// Determines whether the specified s are unequal to each other.
+ ///
+ /// The first
+ /// The second
+ /// True if the s are unequal; otherwise, false
+ public static bool operator !=(MyMenuItems x, MyMenuItems y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines whether the specified is equal to the current .
+ ///
+ /// The to compare with the current
+ /// true if the specified is equal to the current ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is MyMenuItems && this == (MyMenuItems)obj;
+ }
+
+ ///
+ /// Serves as a hash function for a .
+ ///
+ /// A hash code for the current
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = (int)2166136261;
+ hash *= 16777619 ^ MenuItem1.GetHashCode();
+ hash *= 16777619 ^ MenuItem2.GetHashCode();
+ hash *= 16777619 ^ MenuItem3.GetHashCode();
+ hash *= 16777619 ^ MenuItem4.GetHashCode();
+ hash *= 16777619 ^ MenuItem5.GetHashCode();
+ hash *= 16777619 ^ MenuItem6.GetHashCode();
+ return hash;
+ }
+ }
+ }
+}