This commit is contained in:
Tobias Wohlleben 2025-01-18 10:19:15 +01:00
parent 3cd16ac714
commit e06aede5cd
30 changed files with 9813 additions and 0 deletions

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,8 @@
<Application x:Class="CamBooth.App.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CamBooth.App">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -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;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
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>();
mainWindow.Show();
}
private void ConfigureServices(IServiceCollection services)
{
// Register your services and view models here
services.AddTransient<MainWindow>();
services.AddTransient<LiveViewPage>();
services.AddSingleton<Logger>();
}
}

View File

@ -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)
)]

View File

@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\EDSDKLib\EDSDKLib.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Core\Models\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace CamBooth.App.Core.Logging;
public class Logger
{
public void LogInfo(string message)
{
Console.WriteLine(message);
}
}

View File

@ -0,0 +1,12 @@
<Page x:Class="CamBooth.App.DebugConsole.DebugConsolePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CamBooth.App.DebugConsole"
mc:Ignorable="d"
Title="DebugConsolePage" Height="100" Width="800">
<Grid>
<TextBlock>Debug Console</TextBlock>
</Grid>
</Page>

View File

@ -0,0 +1,11 @@
using System.Windows.Controls;
namespace CamBooth.App.DebugConsole;
public partial class DebugConsolePage : Page
{
public DebugConsolePage()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,14 @@
<Page x:Class="CamBooth.App.LiveView.LiveViewPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CamBooth.App.LiveView"
mc:Ignorable="d"
Title="LiveViewPage" Height="550" Width="780"
Background="PaleVioletRed">
<Grid>
<TextBlock>LiveView CamBooth</TextBlock>
<Canvas x:Name="LVCanvas" Background="LightGray" />
</Grid>
</Page>

View File

@ -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<Camera> CamList;
bool IsInit = false;
int BulbTime = 30;
ImageBrush bgbrush = new ImageBrush();
Action<BitmapImage> 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
}

View File

@ -0,0 +1,120 @@

using System.IO;
namespace CamBooth.App.LiveView
{
/// <summary>
/// A stream that does nothing more but wrap another stream (needed for a WPF memory leak)
/// </summary>
public sealed class WrapStream : Stream
{
/// <summary>
/// Gets a value indicating whether the current stream supports reading.
/// </summary>
public override bool CanRead
{
get { return this.Base.CanRead; }
}
/// <summary>
/// Gets a value indicating whether the current stream supports seeking.
/// </summary>
public override bool CanSeek
{
get { return this.Base.CanSeek; }
}
/// <summary>
/// Gets a value indicating whether the current stream supports writing.
/// </summary>
public override bool CanWrite
{
get { return this.Base.CanWrite; }
}
/// <summary>
/// Gets the length in bytes of the stream.
/// </summary>
public override long Length
{
get { return this.Base.Length; }
}
/// <summary>
/// Gets or sets the position within the current stream.
/// </summary>
public override long Position
{
get { return this.Base.Position; }
set { this.Base.Position = value; }
}
private Stream Base;
/// <summary>
/// Creates a new instance of the <see cref="WrapStream"/> class.
/// </summary>
/// <param name="inStream">The stream that gets wrapped</param>
public WrapStream(Stream inStream)
{
this.Base = inStream;
}
/// <summary>
/// reads a sequence of bytes from the current stream and advances
/// the position within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">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.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read
/// from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>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.</returns>
public override int Read(byte[] buffer, int offset, int count)
{
return this.Base.Read(buffer, offset, count);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the
/// current stream.</param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
public override void Write(byte[] buffer, int offset, int count)
{
this.Base.Write(buffer, offset, count);
}
/// <summary>
/// sets the position within the current stream.
/// </summary>
/// <param name="offset">A byte offset relative to the origin parameter.</param>
/// <param name="origin">A value of type System.IO.SeekOrigin indicating the reference point used
/// to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
return this.Base.Seek(offset, origin);
}
/// <summary>
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
/// </summary>
public override void Flush()
{
this.Base.Flush();
}
/// <summary>
/// Sets the length of the current stream.
/// </summary>
/// <param name="value">The desired length of the current stream in bytes.</param>
public override void SetLength(long value)
{
this.Base.SetLength(value);
}
}
}

View File

@ -0,0 +1,43 @@
<Window x:Class="CamBooth.App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CamBooth.App"
mc:Ignorable="d"
Title="MainWindow" Height="650" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- Erste Zeile (Auto-Höhe) -->
<RowDefinition Height="*"/> <!-- Zweite Zeile (flexibler Platz) -->
<RowDefinition Height="Auto"/> <!-- Dritte Zeile (Auto-Höhe) -->
</Grid.RowDefinitions>
<!-- Inhalt der ersten Zeile -->
<Frame Grid.Row="0"
x:Name="MainFrame"
NavigationUIVisibility="Hidden"
HorizontalAlignment="Center"
Background="LightBlue"
VerticalAlignment="Center"
Panel.ZIndex="0" />
<!-- Inhalt der zweiten Zeile (nimmt den verbleibenden Platz ein) -->
<Frame Grid.Row="1"
x:Name="DebugFrame"
NavigationUIVisibility="Hidden"
HorizontalAlignment="Center"
Height="100"
Background="LightGreen"
VerticalAlignment="Bottom"
Panel.ZIndex="1" />
<!-- Inhalt der dritten Zeile -->
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Start" Click="NavToLiveView" Width="200" Background="LightCoral" Height="50" VerticalAlignment="Bottom"/>
<Button Content="Hide Debug" Click="ToggleDebugConsole" Width="200" Background="LightCoral" Height="50" VerticalAlignment="Bottom"/>
</StackPanel>
</Grid>
</Window>

View File

@ -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;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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;
}
}

View File

@ -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

View File

@ -0,0 +1,12 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CDPPDLL_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CDPPLibCom_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CDPPRSC_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CEDSDK_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CEdsImage_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CMlib_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CDev_005CRepos_005CPrivat_005CCamBooth_005Cmisc_005CCanonBinaries_005CUcs32P_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AApplication_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FUsers_003Ftobia_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F6665f2e3e843578225e3796b83c5342a58c3f72bfef19eeee7aa90d157d4949_003FApplication_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FUsers_003Ftobia_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWindow_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FUsers_003Ftobia_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0713c794b56e4feca091d5981a6f5967f60930_003Fc8_003F61b7e802_003FWindow_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWindow_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FUsers_003Ftobia_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fd0db11e55b76dc7f234163f6cee32b297b8ddb591fb0b5cbad1b46ed17343e18_003FWindow_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

File diff suppressed because it is too large Load Diff

View File

@ -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
{
/// <summary>
/// Handles camera connections
/// </summary>
public class CanonAPI : IDisposable
{
#region Events
/// <summary>
/// Fires if a new camera is added
/// </summary>
public event CameraAddedHandler CameraAdded;
/// <summary>
/// The SDK camera added delegate
/// </summary>
protected static SDKCameraAddedHandler CameraAddedEvent;
private ErrorCode CanonAPI_CameraAddedEvent(IntPtr inContext)
{
ThreadPool.QueueUserWorkItem((state) => CameraAdded?.Invoke(this));
return ErrorCode.OK;
}
#endregion
#region Variables
/// <summary>
/// States if the SDK is initialized or not
/// </summary>
public static bool IsSDKInitialized
{
get { return _IsSDKInitialized; }
}
/// <summary>
/// The main SDK thread where the event loop runs
/// </summary>
protected static STAThread MainThread;
/// <summary>
/// Field for the public <see cref="IsSDKInitialized"/> property
/// </summary>
private static bool _IsSDKInitialized;
/// <summary>
/// States if the instance is disposed or not
/// </summary>
private bool IsDisposed;
/// <summary>
/// Number of instances of this class
/// </summary>
private static int RefCount = 0;
/// <summary>
/// Object to lock on to safely de- and increment the <see cref="RefCount"/> value
/// </summary>
private static readonly object InitLock = new object();
/// <summary>
/// List of currently connected cameras (since the last time GetCameraList got called)
/// </summary>
private static List<Camera> CurrentCameras = new List<Camera>();
/// <summary>
/// Object to lock on to safely add/remove cameras from the <see cref="CurrentCameras"/> list
/// </summary>
private static readonly object CameraLock = new object();
#endregion
#region Init/Dispose
/// <summary>
/// Initializes the SDK
/// </summary>
public CanonAPI()
: this(false)
{ }
/// <summary>
/// Initializes the SDK
/// </summary>
/// <param name="useCallingThread">If true, the calling thread will be used as SDK main thread;
/// if false, a separate thread will be created</param>
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;
}
}
/// <summary>
/// Destructor
/// </summary>
~CanonAPI()
{
Dispose(false);
}
/// <summary>
/// Terminates the SDK and disposes resources
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Terminates the SDK and disposes resources
/// </summary>
/// <param name="managed">True if called from Dispose, false if called from the finalizer/destructor</param>
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
/// <summary>
/// Get a list of all cameras connected to the host.
/// <para>If a camera has been connected previously, the same instance of the class is returned.</para>
/// </summary>
/// <returns>A list of connected cameras</returns>
/// <exception cref="ObjectDisposedException">This instance has been disposed already</exception>
/// <exception cref="SDKException">An SDK call failed</exception>
public List<Camera> 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<IntPtr> ptrList = GetCameraPointerList();
List<Camera> camList = new List<Camera>();
//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;
}
}
/// <summary>
/// Get a list of all pointer of the cameras connected to the host
/// </summary>
/// <returns>A list of connected cameras as pointer</returns>
/// <exception cref="ObjectDisposedException">This instance has been disposed already</exception>
/// <exception cref="SDKException">An SDK call failed</exception>
protected IEnumerable<IntPtr> 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<IntPtr> ptrList = new List<IntPtr>();
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;
}
/// <summary>
/// Gets a thumbnail from a Raw or Jpg image
/// </summary>
/// <param name="filepath">Path to the image file</param>
/// <returns>A <see cref="Bitmap"/> thumbnail from the provided image file</returns>
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);
}
}
/// <summary>
/// Gets a <see cref="Bitmap"/> from an EDSDK pointer to an image (Jpg or Raw)
/// </summary>
/// <param name="imgStream">Stream pointer to the image</param>
/// <param name="imageSource">The result image type</param>
/// <returns>A <see cref="Bitmap"/> image from the given stream pointer</returns>
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
}
}

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,282 @@
using EOSDigital.SDK;
namespace EOSDigital.API
{
/// <summary>
/// Stores a camera value
/// </summary>
public class CameraValue
{
/// <summary>
/// The value as a string
/// </summary>
public string StringValue { get; protected set; }
/// <summary>
/// The value as an UInt
/// </summary>
public int IntValue { get; protected set; }
/// <summary>
/// The value as a double
/// </summary>
public double DoubleValue { get; protected set; }
/// <summary>
/// The property ID of this value
/// </summary>
public PropertyID ValueType { get; protected set; }
/// <summary>
/// Creates a new instance of the <see cref="CameraValue"/> class
/// </summary>
protected CameraValue()
{
ValueType = PropertyID.Unknown;
StringValue = "N/A";
IntValue = unchecked((int)0xFFFFFFFF);
DoubleValue = 0.0;
}
/// <summary>
/// Creates a new camera value
/// </summary>
/// <param name="Value">The value as a string</param>
/// <param name="ValueType">The property ID of the value</param>
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;
}
}
/// <summary>
/// Creates a new camera value
/// </summary>
/// <param name="Value">The value as an uint</param>
/// <param name="ValueType">The property ID of the value</param>
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;
}
}
/// <summary>
/// Creates a new camera value
/// </summary>
/// <param name="Value">The value as a double</param>
/// <param name="ValueType">The property ID of the value</param>
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;
}
/// <summary>
/// Determines whether the specified <see cref="CameraValue"/>s are equal to each other.
/// </summary>
/// <param name="x">The first <see cref="CameraValue"/></param>
/// <param name="y">The second <see cref="CameraValue"/></param>
/// <returns>True if the <see cref="CameraValue"/>s are equal; otherwise, false</returns>
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;
}
/// <summary>
/// Determines whether the specified <see cref="CameraValue"/>s are unequal to each other.
/// </summary>
/// <param name="x">The first <see cref="CameraValue"/></param>
/// <param name="y">The second <see cref="CameraValue"/></param>
/// <returns>True if the <see cref="CameraValue"/>s are unequal; otherwise, false</returns>
public static bool operator !=(CameraValue x, CameraValue y)
{
return !(x == y);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to the current <see cref="CameraValue"/>.
/// </summary>
/// <param name="obj">The <see cref="object"/> to compare with the current <see cref="CameraValue"/></param>
/// <returns>true if the specified <see cref="object"/> is equal to the current <see cref="CameraValue"/>; otherwise, false.</returns>
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;
}
/// <summary>
/// Serves as a hash function for a <see cref="CameraValue"/>.
/// </summary>
/// <returns>A hash code for the current <see cref="CameraValue"/></returns>
public override int GetHashCode()
{
unchecked
{
int hash = (int)2166136261;
hash *= 16777619 ^ IntValue.GetHashCode();
hash *= 16777619 ^ ValueType.GetHashCode();
return hash;
}
}
/// <summary>
/// Implicitly converts the camera value to an int
/// </summary>
/// <param name="x">The camera value to convert</param>
/// <returns>The int representing the camera value</returns>
public static implicit operator int(CameraValue x)
{
return x.IntValue;
}
/// <summary>
/// Implicitly converts the camera value to a string
/// </summary>
/// <param name="x">The camera value to convert</param>
/// <returns>The string representing the camera value</returns>
public static implicit operator string(CameraValue x)
{
return x.StringValue;
}
/// <summary>
/// Implicitly converts the camera value to a double
/// </summary>
/// <param name="x">The camera value to convert</param>
/// <returns>The double representing the camera value</returns>
public static implicit operator double(CameraValue x)
{
return x.DoubleValue;
}
/// <summary>
/// Returns a string that represents the current <see cref="CameraValue"/>.
/// </summary>
/// <returns>A string that represents the current <see cref="CameraValue"/>.</returns>
public override string ToString()
{
return StringValue;
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.IO;
using EOSDigital.SDK;
namespace EOSDigital.API
{
/// <summary>
/// A delegate for progress
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="progress">The progress. A value between 0 and 100</param>
public delegate void ProgressHandler(object sender, int progress);
/// <summary>
/// A delegate to pass a stream
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="img">An image embedded in a stream</param>
public delegate void LiveViewUpdate(Camera sender, Stream img);
/// <summary>
/// A delegate to report an available download
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="Info">The data for the download</param>
public delegate void DownloadHandler(Camera sender, DownloadInfo Info);
/// <summary>
/// A delegate for property changes
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="eventID">The property event ID</param>
/// <param name="propID">The property ID</param>
/// <param name="parameter">A parameter for additional information</param>
public delegate void PropertyChangeHandler(Camera sender, PropertyEventID eventID, PropertyID propID, int parameter);
/// <summary>
/// A delegate for camera state changes
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="eventID">The state event ID</param>
/// <param name="parameter">A parameter for additional information</param>
public delegate void StateChangeHandler(Camera sender, StateEventID eventID, int parameter);
/// <summary>
/// A delegate for property changes
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="eventID">The object event ID</param>
/// <param name="reference">A pointer to the object that has changed</param>
public delegate void ObjectChangeHandler(Camera sender, ObjectEventID eventID, IntPtr reference);
/// <summary>
/// A delegate to inform of an added camera
/// </summary>
/// <param name="sender">The sender of this event</param>
public delegate void CameraAddedHandler(CanonAPI sender);
/// <summary>
/// A delegate to inform of a change of a camera
/// </summary>
/// <param name="sender">The sender of this event</param>
public delegate void CameraUpdateHandler(Camera sender);
/// <summary>
/// A delegate to inform of SDK exceptions
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="ex">The SDK exception</param>
public delegate void SDKExceptionHandler(object sender, ErrorCode ex);
/// <summary>
/// A delegate to inform of exceptions
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="ex">The exception</param>
public delegate void GeneralExceptionHandler(object sender, Exception ex);
}

View File

@ -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
{
/// <summary>
/// An Exception that happened while handling the Canon SDK
/// </summary>
[Serializable]
public sealed class SDKException : Exception
{
/// <summary>
/// The specific SDK error code that happened
/// </summary>
public ErrorCode Error { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class
/// </summary>
public SDKException()
{
Error = ErrorCode.INTERNAL_ERROR;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with a specified error code
/// </summary>
/// <param name="Error">The SDK error code of the error that happened</param>
public SDKException(ErrorCode Error)
: base(Error.ToString())
{
this.Error = Error;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with a specified error message
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public SDKException(string message)
: base(message)
{
Error = ErrorCode.INTERNAL_ERROR;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with a specified
/// error message and a reference to the inner exception that is the cause of
/// this exception
/// </summary>
/// <param name="message">The error message that explains the reason for the exception</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
/// (Nothing in Visual Basic) if no inner exception is specified</param>
public SDKException(string message, Exception innerException)
: base(message, innerException)
{
Error = ErrorCode.INTERNAL_ERROR;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with a specified error message and error code
/// </summary>
/// <param name="Error">The SDK error code of the error that happened</param>
/// <param name="message">The error message that explains the reason for the exception</param>
public SDKException(string message, ErrorCode Error)
: base(message)
{
this.Error = Error;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with a specified
/// error message, error code and a reference to the inner exception that is the cause of
/// this exception
/// </summary>
/// <param name="message">The error message that explains the reason for the exception</param>
/// <param name="Error">The SDK error code of the error that happened</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
/// (Nothing in Visual Basic) if no inner exception is specified.</param>
public SDKException(string message, ErrorCode Error, Exception innerException)
: base(message, innerException)
{
this.Error = Error;
}
/// <summary>
/// Initializes a new instance of the <see cref="SDKException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized
/// object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual
/// information about the source or destination.</param>
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private SDKException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
Error = (ErrorCode)info.GetUInt32("Error");
}
/// <summary>
/// When overridden in a derived class, sets the <see cref="SerializationInfo"/>
/// with information about the exception.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/>
/// that holds the serialized object data about the exception being thrown</param>
/// <param name="context">The <see cref="StreamingContext"/>
/// that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">The info parameter is a null reference</exception>
[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);
}
}
/// <summary>
/// An Exception that states a problem with the session state of the camera
/// </summary>
[Serializable]
public sealed class CameraSessionException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="CameraSessionException"/> class
/// </summary>
public CameraSessionException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CameraSessionException"/> class with a specified error message
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public CameraSessionException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CameraSessionException"/> class with a specified
/// error message and a reference to the inner exception that is the cause of
/// this exception
/// </summary>
/// <param name="message">The error message that explains the reason for the exception</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
/// (Nothing in Visual Basic) if no inner exception is specified</param>
public CameraSessionException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CameraSessionException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized
/// object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual
/// information about the source or destination.</param>
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private CameraSessionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// When overridden in a derived class, sets the <see cref="SerializationInfo"/>
/// with information about the exception.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/>
/// that holds the serialized object data about the exception being thrown</param>
/// <param name="context">The <see cref="StreamingContext"/>
/// that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">The info parameter is a null reference</exception>
[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);
}
}
/// <summary>
/// An Exception that states a problem with the state of the Canon SDK
/// </summary>
[Serializable]
public sealed class SDKStateException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="SDKStateException"/> class
/// </summary>
public SDKStateException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="SDKStateException"/> class with a specified error message
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public SDKStateException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="SDKStateException"/> class with a specified
/// error message and a reference to the inner exception that is the cause of
/// this exception
/// </summary>
/// <param name="message">The error message that explains the reason for the exception</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
/// (Nothing in Visual Basic) if no inner exception is specified</param>
public SDKStateException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="SDKStateException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized
/// object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual
/// information about the source or destination.</param>
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private SDKStateException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// When overridden in a derived class, sets the <see cref="SerializationInfo"/>
/// with information about the exception.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/>
/// that holds the serialized object data about the exception being thrown</param>
/// <param name="context">The <see cref="StreamingContext"/>
/// that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">The info parameter is a null reference</exception>
[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);
}
}
/// <summary>
/// An Exception that happened while executing on an STA thread
/// </summary>
[Serializable]
public sealed class ExecutionException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="ExecutionException"/> class with a specified error message
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public ExecutionException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ExecutionException"/> class with a reference to
/// the inner exception that is the cause of this exception
/// </summary>
/// <param name="message">The error message that explains the reason for the exception</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
/// (Nothing in Visual Basic) if no inner exception is specified</param>
public ExecutionException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ExecutionException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized
/// object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual
/// information about the source or destination.</param>
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private ExecutionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// When overridden in a derived class, sets the <see cref="SerializationInfo"/>
/// with information about the exception.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/>
/// that holds the serialized object data about the exception being thrown</param>
/// <param name="context">The <see cref="StreamingContext"/>
/// that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">The info parameter is a null reference</exception>
[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);
}
}
/// <summary>
/// Handles errors and provides events for errors (e.g. focus problems or general exceptions)
/// </summary>
public static class ErrorHandler
{
/// <summary>
/// If an error happened, that does not break the program, this event is fired (e.g. a focus error)
/// </summary>
public static event SDKExceptionHandler NonSevereErrorHappened;
/// <summary>
/// If an error happened on a thread that does not fall into the non-severe category, this event is fired
/// </summary>
public static event GeneralExceptionHandler SevereErrorHappened;
/// <summary>
/// List of all non-severe errors. Items can be added or removed.
/// </summary>
public static List<ErrorCode> NonSevereErrors { get; private set; }
static ErrorHandler()
{
NonSevereErrors = new List<ErrorCode>()
{
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,
};
}
/// <summary>
/// Checks for an error in SDK calls and checks how to treat it
/// </summary>
/// <param name="sender">The sender object</param>
/// <param name="errorCode">The return code of the SDK call</param>
/// <exception cref="SDKException">If a severe error is recognized or the <see cref="NonSevereErrorHappened"/>
/// event is null with a non-severe error, it will be thrown as an exception</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);
}
}
/// <summary>
/// Checks for an error in SDK calls and throws an exception if it's not <see cref="ErrorCode.OK"/>
/// </summary>
/// <param name="errorCode">The return code of the SDK call</param>
/// <exception cref="SDKException">If <paramref name="errorCode"/> is something other than <see cref="ErrorCode.OK"/></exception>
public static void CheckError(ErrorCode errorCode)
{
if (errorCode != ErrorCode.OK) throw new SDKException(errorCode);
}
/// <summary>
/// Checks for an error in <see cref="CanonSDK.EdsRetain"/> and <see cref="CanonSDK.EdsRelease"/> calls
/// and throws an exception if it's not valid
/// </summary>
/// <param name="countOrError">The return code of the SDK call</param>
/// <returns>The number of references for the pointer that was used for the SDK call</returns>
public static int CheckError(int countOrError)
{
if (countOrError == unchecked((int)0xFFFFFFFF)) throw new SDKException(ErrorCode.INVALID_HANDLE);
else return countOrError;
}
/// <summary>
/// Checks for an error in <see cref="CanonSDK.EdsRetain"/> and <see cref="CanonSDK.EdsRelease"/> calls
/// and throws an exception if it's not valid
/// </summary>
/// <param name="sender">The calling object instance. This is currently not used and is ignored.</param>
/// <param name="countOrError">The return code of the SDK call</param>
/// <returns>The number of references for the pointer that was used for the SDK call</returns>
public static int CheckError(object sender, int countOrError)
{
return CheckError(countOrError);
}
/// <summary>
/// Reports an error that happened in a threading environment
/// </summary>
/// <param name="sender">The sender object</param>
/// <param name="ex">The exception that happened</param>
/// <returns>True if the error could be passed on; false otherwise</returns>
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;
}
}
}
}

View File

@ -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
{
/// <summary>
/// Stores information to download data from the camera
/// </summary>
public class DownloadInfo
{
/// <summary>
/// Pointer to the downloadable object
/// </summary>
protected IntPtr inRef;
/// <summary>
/// Directory item info of the downloadable object
/// </summary>
protected DirectoryItemInfo dirInfo;
/// <summary>
/// Pointer to the downloadable object
/// </summary>
public IntPtr Reference { get { return inRef; } }
/// <summary>
/// The name of the file. You can change it before you pass it to the
/// <see cref="Camera.DownloadFile(DownloadInfo)"/> or
/// <see cref="Camera.DownloadFile(DownloadInfo, string)"/> method.
/// </summary>
public string FileName
{
get { return dirInfo.FileName; }
set { dirInfo.FileName = value; }
}
/// <summary>
/// The files size in bytes
/// </summary>
public int Size { get { return dirInfo.Size; } }
/// <summary>
/// The files size in bytes (as ulong)
/// </summary>
public long Size64 { get { return dirInfo.Size64; } }
/// <summary>
/// States if the file is a RAW file or not
/// </summary>
public bool IsRAW { get; protected set; }
/// <summary>
/// Creates a new instance of the <see cref="DownloadInfo"/> class
/// </summary>
/// <param name="inRef">Pointer to the downloadable object</param>
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;
}
}
/// <summary>
/// Stores information about a file or folder in a camera
/// </summary>
public partial class CameraFileEntry : IDisposable
{
/// <summary>
/// Pointer to the file entry
/// </summary>
public IntPtr Reference { get { return Ref; } }
/// <summary>
/// The name of the entry. (volume name, folder name or file name)
/// </summary>
public string Name { get; protected set; }
/// <summary>
/// States if the entry is a folder or not
/// </summary>
public bool IsFolder { get; protected set; }
/// <summary>
/// States if the entry is a volume or not
/// </summary>
public bool IsVolume { get; protected set; }
/// <summary>
/// If the entry is a volume or folder, these are the subentries it contains. It's null if no subentries are present.
/// </summary>
public CameraFileEntry[] Entries { get; internal protected set; }
/// <summary>
/// Pointer to the file entry
/// </summary>
protected IntPtr Ref;
/// <summary>
/// States if the entry is disposed or not
/// </summary>
internal protected bool IsDisposed;
/// <summary>
/// Creates a new instance of the <see cref="CameraFileEntry"/> class
/// </summary>
/// <param name="Ref"></param>
/// <param name="Name"></param>
/// <param name="IsFolder"></param>
/// <param name="IsVolume"></param>
internal protected CameraFileEntry(IntPtr Ref, string Name, bool IsFolder, bool IsVolume)
{
this.Ref = Ref;
this.Name = Name;
this.IsFolder = IsFolder;
this.IsVolume = IsVolume;
}
/// <summary>
/// Destructor
/// </summary>
~CameraFileEntry()
{
Dispose(false);
}
/// <summary>
/// Releases this entry but not the subentries
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases this entry and all the subentries
/// </summary>
public void DisposeAll()
{
Dispose();
if (Entries != null) for (int i = 0; i < Entries.Length; i++) Entries[i].DisposeAll();
}
/// <summary>
/// Releases this entry but not the subentries
/// </summary>
/// <param name="managed">True if called from Dispose, false if called from the finalizer/destructor</param>
protected virtual void Dispose(bool managed)
{
if (!IsDisposed)
{
if (managed) DisposeThumb();
if (Reference != IntPtr.Zero) CanonSDK.EdsRelease(Reference);
IsDisposed = true;
}
}
/// <summary>
/// Dispose the thumbnail in an extension
/// </summary>
partial void DisposeThumb();
/// <summary>
/// Set the thumbnail from a stream. The thumbnail depends on the image class you want to use.
/// </summary>
/// <param name="stream">The image stream</param>
internal protected virtual void SetThumb(IntPtr stream)
{
SetThumbSub(stream);
}
/// <summary>
/// Sets the thumbnail
/// </summary>
/// <param name="stream">The image stream</param>
partial void SetThumbSub(IntPtr stream);
/// <summary>
/// Determines whether the specified <see cref="CameraFileEntry"/>s are equal to each other.
/// </summary>
/// <param name="x">The first <see cref="CameraFileEntry"/></param>
/// <param name="y">The second <see cref="CameraFileEntry"/></param>
/// <returns>True if the <see cref="CameraFileEntry"/>s are equal; otherwise, false</returns>
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;
}
/// <summary>
/// Determines whether the specified <see cref="CameraFileEntry"/>s are unequal to each other.
/// </summary>
/// <param name="x">The first <see cref="CameraFileEntry"/></param>
/// <param name="y">The second <see cref="CameraFileEntry"/></param>
/// <returns>True if the <see cref="CameraFileEntry"/>s are unequal; otherwise, false</returns>
public static bool operator !=(CameraFileEntry x, CameraFileEntry y)
{
return !(x == y);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to the current <see cref="CameraFileEntry"/>.
/// </summary>
/// <param name="obj">The <see cref="object"/> to compare with the current <see cref="CameraFileEntry"/></param>
/// <returns>true if the specified <see cref="object"/> is equal to the current <see cref="CameraFileEntry"/>; otherwise, false.</returns>
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;
}
/// <summary>
/// Serves as a hash function for a <see cref="CameraFileEntry"/>.
/// </summary>
/// <returns>A hash code for the current <see cref="CameraFileEntry"/></returns>
public override int GetHashCode()
{
return Reference.ToInt64().GetHashCode();
}
}
/// <summary>
/// A Stream encapsulating an unmanaged SDK Stream.
/// This class can be used to overcome the differences between SDK versions
/// </summary>
public class SDKStream : Stream
{
/// <summary>
/// Gets a value indicating whether the current stream supports reading.
/// </summary>
public override bool CanRead
{
get { return true; }
}
/// <summary>
/// Gets a value indicating whether the current stream supports seeking.
/// </summary>
public override bool CanSeek
{
get { return true; }
}
/// <summary>
/// Gets a value indicating whether the current stream supports writing.
/// </summary>
public override bool CanWrite
{
get { return true; }
}
/// <summary>
/// Gets the length in bytes of the stream.
/// </summary>
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;
}
}
}
/// <summary>
/// Gets or sets the position within the current stream.
/// </summary>
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); }
}
/// <summary>
/// Pointer to the underlying SDK stream
/// </summary>
public IntPtr Reference
{
get { return _Reference; }
protected set { _Reference = value; }
}
private IntPtr _Reference;
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class from an existing SDK stream
/// </summary>
/// <param name="sdkStream">Pointer to the SDK stream</param>
public SDKStream(IntPtr sdkStream)
{
if (sdkStream == IntPtr.Zero) throw new ArgumentNullException(nameof(sdkStream));
Reference = sdkStream;
}
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK file stream
/// </summary>
/// <param name="filepath">Path to the file</param>
/// <param name="createDisposition">State how to create the stream</param>
/// <param name="access">File access type</param>
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));
}
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream.
/// This stream will resize itself if the current length is exceeded
/// </summary>
/// <param name="length">Initial buffer size of the stream in bytes</param>
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);
}
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream.
/// Note that this stream will not resize itself
/// </summary>
/// <param name="buffer">The memory buffer to use for the stream</param>
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);
}
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream.
/// Note that this stream will not resize itself
/// </summary>
/// <param name="buffer">Pointer to the memory buffer to use for the stream</param>
/// <param name="length">The size of the memory buffer in bytes</param>
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);
}
/// <summary>
/// Creates a new instance of the <see cref="SDKStream"/> class from an existing SDK stream.
/// Note that this calls <see cref="SDKStream(IntPtr)"/> internally and ignores all parameters but <paramref name="sdkStream"/>
/// </summary>
/// <param name="buffer">Pointer to the underlying SDK buffer. Ignored parameter</param>
/// <param name="sdkStream">Pointer to the SDK stream</param>
/// <param name="length">The size of the underlying SDK buffer in bytes. Ignored parameter</param>
[Obsolete("Not necessary anymore. Buffer and length is not used.")]
public SDKStream(IntPtr buffer, IntPtr sdkStream, long length)
: this(sdkStream)
{ }
/// <summary>
/// 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.
/// </summary>
public override void Flush()
{
//Nothing to do here
}
/// <summary>
/// Reads a sequence of bytes from the current stream and advances the position
/// within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">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.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read
/// from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>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.</returns>
public override int Read(byte[] buffer, int offset, int count)
{
return (int)Read(buffer, offset, count);
}
/// <summary>
/// Reads a sequence of bytes from the current stream and advances the position
/// within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">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.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read
/// from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>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.</returns>
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;
}
}
}
/// <summary>
/// Sets the position within the current stream.
/// </summary>
/// <param name="offset">A byte offset relative to the origin parameter.</param>
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
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;
}
/// <summary>
/// Always throws a <see cref="NotSupportedException"/>
/// </summary>
/// <param name="value">The desired length of the current stream in bytes.</param>
public override void SetLength(long value)
{
throw new NotSupportedException();
}
/// <summary>
/// Writes a sequence of bytes to the current stream and advances
/// the current position within this stream by the number of bytes written.
/// </summary>
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
public override void Write(byte[] buffer, int offset, int count)
{
Write(buffer, (long)offset, count);
}
/// <summary>
/// Writes a sequence of bytes to the current stream and advances
/// the current position within this stream by the number of bytes written.
/// </summary>
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
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));
}
}
}
/// <summary>
/// Releases the unmanaged resources used by the <see cref="SDKStream"/> and optionally
/// releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources;
/// false to release only unmanaged</param>
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);
}
}
}
}

View File

@ -0,0 +1,324 @@
using System;
using System.Threading;
namespace EOSDigital.API
{
/// <summary>
/// This static class executes things on an STA thread and provides a method to create an STA thread
/// </summary>
public class STAThread
{
#region Variables
/// <summary>
/// Object that is used for the lock keyword to ensure only one SDK command is executed at a time
/// </summary>
public static readonly object ExecLock = new object();
/// <summary>
/// States if the calling thread is in a Single Threaded Apartment or not
/// </summary>
public static bool IsSTAThread
{
get { return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA; }
}
/// <summary>
/// States if this thread is currently running
/// </summary>
public bool IsRunning
{
get { return isRunning; }
}
/// <summary>
/// ID of the associated thread
/// </summary>
public int ThreadID
{
get { return mainThread.ManagedThreadId; }
}
/// <summary>
/// The main thread where everything will be executed on
/// </summary>
private Thread mainThread;
/// <summary>
/// States if the execution thread is currently running
/// </summary>
private bool isRunning = false;
/// <summary>
/// Lock object to make sure only one command at a time is executed
/// </summary>
private object runLock = new object();
/// <summary>
/// Lock object to ensure that an action executed on the thread does not invoke on itself
/// </summary>
private object cmdLock = new object();
/// <summary>
/// Lock object to synchronize between execution and calling thread
/// </summary>
protected object threadLock1 = new object();
/// <summary>
/// Lock object to synchronize between execution and calling thread
/// </summary>
private object threadLock2 = new object();
/// <summary>
/// States if the first lock is currently blocking or not
/// </summary>
protected bool block1 = true;
/// <summary>
/// States if the second lock is currently blocking or not
/// </summary>
private bool block2 = true;
/// <summary>
/// The action to be executed
/// </summary>
private Action runAction;
/// <summary>
/// Storage for an exception that might have happened on the execution thread
/// </summary>
private Exception runException;
#endregion
/// <summary>
/// Creates a new instance of the <see cref="STAThread"/> class
/// </summary>
internal STAThread()
{ }
#region Public Methods
/// <summary>
/// Starts the execution loop
/// </summary>
public void Start()
{
lock (runLock)
{
if (!isRunning)
{
mainThread = CreateThread(ExecutionLoop);
isRunning = true;
mainThread.Start();
WaitForThread();
}
}
}
/// <summary>
/// Shuts down the execution loop and waits for it to finish
/// </summary>
public void Shutdown()
{
lock (runLock)
{
if (isRunning)
{
isRunning = false;
NotifyThread();
mainThread.Join();
}
}
}
/// <summary>
/// Executes an action on this STA thread
/// </summary>
/// <param name="action">The action to execute</param>
/// <exception cref="ArgumentNullException">will be thrown if action is null</exception>
/// <exception cref="ExecutionException">if an exception is thrown on the thread,
/// it will be rethrown as inner exception of this exception</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);
}
}
}
/// <summary>
/// Executes a function on this STA thread
/// </summary>
/// <param name="func">The function to execute</param>
/// <returns>the return value of the function</returns>
/// <exception cref="ArgumentNullException">will be thrown if func is null</exception>
/// <exception cref="ExecutionException">if an exception is thrown on the thread,
/// it will be rethrown as inner exception of this exception</exception>
public T Invoke<T>(Func<T> func)
{
if (func == null) throw new ArgumentNullException(nameof(func));
T result = default(T);
Invoke(delegate { result = func(); });
return result;
}
#endregion
#region Static Methods
/// <summary>
/// Creates a thread in a Single Threaded Apartment
/// </summary>
/// <param name="action">The command to run on this thread</param>
/// <returns>An STA thread</returns>
public static Thread CreateThread(Action action)
{
var thread = new Thread(new ThreadStart(action));
thread.SetApartmentState(ApartmentState.STA);
return thread;
}
/// <summary>
/// Executes an action on a newly created STA Thread
/// and optionally waits for it to finish executing
/// </summary>
/// <param name="action">The action to execute</param>
/// <param name="wait">If true, the action is executed synchronously or if false, asynchronously.</param>
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);
}
}
/// <summary>
/// Executes a function on a newly created STA Thread
/// </summary>
/// <param name="func">The function to execute</param>
/// <returns>The return value of the given function</returns>
public static T ExecuteThread<T>(Func<T> 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
/// <summary>
/// Notifies the execution loop to execute something
/// </summary>
private void NotifyThread()
{
lock (threadLock1)
{
block1 = false;
Monitor.Pulse(threadLock1);
}
}
/// <summary>
/// Blocks until the execution loop is done with the work
/// </summary>
private void WaitForThread()
{
lock (threadLock2)
{
while (block2) Monitor.Wait(threadLock2);
block2 = true;
}
}
/// <summary>
/// Releases the waiting <see cref="WaitForThread"/> method to continue
/// </summary>
private void ReleaseWait()
{
lock (threadLock2)
{
block2 = false;
Monitor.Pulse(threadLock2);
}
}
/// <summary>
/// The waiting routine on the execution loop
/// </summary>
protected virtual void WaitForNotification()
{
lock (threadLock1)
{
while (block1 && isRunning) { Monitor.Wait(threadLock1); }
block1 = true;
}
}
/// <summary>
/// The loop that is executed on the thread and where the work is done
/// </summary>
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
}
}

View File

@ -0,0 +1,788 @@
using System;
using System.Linq;
using System.Collections.Generic;
using EOSDigital.SDK;
namespace EOSDigital.API
{
/// <summary>
/// Stores CameraValues and provides methods to get those values. Abstract class.
/// </summary>
public abstract class ValueBase
{
/// <summary>
/// Get the value from an int out of given possible values.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <param name="Values">Possible values that will be searched for the given value</param>
/// <returns>The CameraValue with given uint representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value, List<CameraValue> 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]; }
}
/// <summary>
/// Get the value from a string out of given possible values.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <param name="Values">Possible values that will be searched for the given value</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value, List<CameraValue> 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]; }
}
/// <summary>
/// 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.
/// </summary>
/// <param name="value">The value to get</param>
/// <param name="Values">Possible values that will be searched for the given value</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value, List<CameraValue> 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];
}
/// <summary>
/// Comparer for <see cref="CameraValue"/>s
/// </summary>
protected sealed class CameraValueComparer : IEqualityComparer<CameraValue>
{
/// <summary>
/// Determines whether the specified <see cref="CameraValue"/>s are equal.
/// </summary>
/// <param name="x">The first <see cref="CameraValue"/></param>
/// <param name="y">The second <see cref="CameraValue"/></param>
/// <returns>true if the specified <see cref="CameraValue"/>s are equal; otherwise, false.</returns>
public bool Equals(CameraValue x, CameraValue y)
{
return x.Equals(y);
}
/// <summary>
/// Serves as a hash function for a <see cref="CameraValue"/>.
/// </summary>
/// <returns>A hash code for the current <see cref="CameraValue"/></returns>
public int GetHashCode(CameraValue obj)
{
return obj.GetHashCode();
}
}
}
/// <summary>
/// Stores Av Values and provides methods to get those values
/// </summary>
public sealed class AvValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> values;
/// <summary>
/// The Av <see cref="CameraValue"/> of the "Auto" or "None" setting
/// </summary>
public static readonly CameraValue Auto = new CameraValue("Auto", 0x00000000, 0, PropertyID.Av);
/// <summary>
/// The Av <see cref="CameraValue"/> of an invalid setting
/// </summary>
public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.Av);
static AvValues()
{
values = new List<CameraValue>()
{
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
};
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
/// <summary>
/// Stores Tv Values and provides methods to get those values
/// </summary>
public sealed class TvValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> values;
/// <summary>
/// The Tv <see cref="CameraValue"/> of the "Auto" setting
/// </summary>
public static readonly CameraValue Auto = new CameraValue("Auto", 0x00000000, 0, PropertyID.Tv);
/// <summary>
/// The Tv <see cref="CameraValue"/> of the "Bulb" setting
/// </summary>
public static readonly CameraValue Bulb = new CameraValue("Bulb", 0x0C, 0, PropertyID.Tv);
/// <summary>
/// The Tv <see cref="CameraValue"/> of an invalid setting
/// </summary>
public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.Tv);
static TvValues()
{
values = new List<CameraValue>()
{
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
};
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
/// <summary>
/// Stores ISO Values and provides methods to get those values
/// </summary>
public sealed class ISOValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> values;
/// <summary>
/// The ISO <see cref="CameraValue"/> of the "Auto" setting
/// </summary>
public static readonly CameraValue Auto = new CameraValue("ISO Auto", 0x00000000, 0, PropertyID.ISO);
/// <summary>
/// The ISO <see cref="CameraValue"/> of an invalid setting
/// </summary>
public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.ISO);
static ISOValues()
{
values = new List<CameraValue>()
{
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
};
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
/// <summary>
/// Stores Exposure Compensation Values and provides methods to get those values
/// </summary>
public sealed class ExpCompValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> values;
/// <summary>
/// The ExposureCompensation <see cref="CameraValue"/> of Zero
/// </summary>
public static readonly CameraValue Zero = new CameraValue("0", 0x00, 0, PropertyID.ExposureCompensation);
/// <summary>
/// The ExposureCompensation <see cref="CameraValue"/> of an invalid setting
/// </summary>
public static readonly CameraValue Invalid = new CameraValue("N/A", unchecked((int)0xFFFFFFFF), 0, PropertyID.ExposureCompensation);
static ExpCompValues()
{
values = new List<CameraValue>()
{
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
};
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
/// <summary>
/// Stores AE Mode Values and provides methods to get those values
/// </summary>
public sealed class AEModeValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> 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<CameraValue>();
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);
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
/// <summary>
/// Stores Metering Mode Values and provides methods to get those values
/// </summary>
public sealed class MeteringModeValues : ValueBase
{
/// <summary>
/// All values for this property
/// </summary>
public static CameraValue[] Values { get { return values.ToArray(); } }
private static List<CameraValue> 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<CameraValue>();
values.Add(Spot);
values.Add(Evaluative);
values.Add(Partial);
values.Add(CenterWeightedAveraging);
values.Add(NotValid);
}
/// <summary>
/// Get the value from an int.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of the value to get</param>
/// <returns>The CameraValue with given int representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(int value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a string.
/// It has to be an exact match, otherwise an exception is thrown.
/// </summary>
/// <param name="value">The ID of value to get</param>
/// <returns>The CameraValue with given string representation</returns>
/// <exception cref="KeyNotFoundException">No <see cref="CameraValue"/> for the given value</exception>
public static CameraValue GetValue(string value)
{
return GetValue(value, values);
}
/// <summary>
/// Get the value from a double.
/// It searches for the closest representation and therefore might not return the exact input value.
/// </summary>
/// <param name="value">The value to get</param>
/// <returns>The CameraValue with given double representation</returns>
public static CameraValue GetValue(double value)
{
return GetValue(value, values);
}
}
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{15E99248-6161-46A4-9183-609CA62406A6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EDSDKLib</RootNamespace>
<AssemblyName>EDSDKLib</AssemblyName>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>8</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\EDSDKLib.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
</ItemGroup>
<ItemGroup>
<Compile Include="API\Base\Camera.cs" />
<Compile Include="API\Base\CanonAPI.cs" />
<Compile Include="API\Helper\ApiThread.cs" />
<Compile Include="API\Helper\CameraValue.cs" />
<Compile Include="API\Helper\Delegates.cs" />
<Compile Include="API\Helper\ExceptionHandling.cs" />
<Compile Include="API\Helper\IO.cs" />
<Compile Include="API\Helper\STAThread.cs" />
<Compile Include="API\Helper\ValueCollections.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SDK\SDKDelegates.cs" />
<Compile Include="SDK\SDKEnums.cs" />
<Compile Include="SDK\SDKMethods.cs" />
<Compile Include="SDK\SDKStructs.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -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")]

View File

@ -0,0 +1,44 @@
using System;
namespace EOSDigital.SDK
{
/// <summary>
/// A delegate for progress.
/// </summary>
/// <param name="inPercent">The progress. A value between 0 and 100</param>
/// <param name="inContext">Reference to the object the progress is about</param>
/// <param name="outCancel">Pass true to cancel the underlying process</param>
/// <returns></returns>
public delegate ErrorCode SDKProgressCallback(int inPercent, IntPtr inContext, ref bool outCancel);
/// <summary>
/// A delegate for property events.
/// </summary>
/// <param name="inEvent">The property event ID</param>
/// <param name="inPropertyID">The property ID</param>
/// <param name="inParameter">A parameter for additional information</param>
/// <param name="inContext">A reference to the object that has sent the event</param>
/// <returns>Any of the SDK errors</returns>
public delegate ErrorCode SDKPropertyEventHandler(PropertyEventID inEvent, PropertyID inPropertyID, int inParameter, IntPtr inContext);
/// <summary>
/// A delegate for object events.
/// </summary>
/// <param name="inEvent">The object event ID</param>
/// <param name="inRef">A pointer to the object that has changed</param>
/// <param name="inContext">A reference to the object that has sent the event</param>
/// <returns>Any of the SDK errors</returns>
public delegate ErrorCode SDKObjectEventHandler(ObjectEventID inEvent, IntPtr inRef, IntPtr inContext);
/// <summary>
/// A delegate for state events.
/// </summary>
/// <param name="inEvent">The state event ID</param>
/// <param name="inParameter">A parameter for additional information</param>
/// <param name="inContext">A reference to the object that has sent the event</param>
/// <returns>Any of the SDK errors</returns>
public delegate ErrorCode SDKStateEventHandler(StateEventID inEvent, int inParameter, IntPtr inContext);
/// <summary>
/// A delegate to inform of an added camera.
/// </summary>
/// <param name="inContext">A reference to the added camera</param>
/// <returns>Any of the SDK errors</returns>
public delegate ErrorCode SDKCameraAddedHandler(IntPtr inContext);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff