mirror of
https://github.com/soukoku/ntwain.git
synced 2025-09-18 17:47:57 +08:00
Added transfer logic skeleton from old code.
This commit is contained in:
@@ -31,4 +31,164 @@ namespace NTwain
|
||||
/// </summary>
|
||||
public bool UIOnly { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Contains event data when a data transfer is ready to be processed.
|
||||
/// </summary>
|
||||
public class TransferReadyEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransferReadyEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="pendingCount">The pending count.</param>
|
||||
/// <param name="endOfJobFlag"></param>
|
||||
public TransferReadyEventArgs(DataSource source, int pendingCount, EndXferJob endOfJobFlag)
|
||||
{
|
||||
DataSource = source;
|
||||
PendingTransferCount = pendingCount;
|
||||
EndOfJobFlag = endOfJobFlag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data source.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The data source.
|
||||
/// </value>
|
||||
public DataSource DataSource { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the current transfer should be canceled
|
||||
/// and continue next transfer if there are more data.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to cancel current transfer; otherwise, <c>false</c>.</value>
|
||||
public bool CancelCurrent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether all transfers should be canceled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to cancel all transfers; otherwise, <c>false</c>.</value>
|
||||
public bool CancelAll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether current transfer signifies an end of job in TWAIN world.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if transfer is end of job; otherwise, <c>false</c>.</value>
|
||||
public bool EndOfJob { get { return EndOfJobFlag != EndXferJob.None; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the end of job flag value for this transfer (if job control is enabled).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The end of job flag.
|
||||
/// </value>
|
||||
public EndXferJob EndOfJobFlag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the known pending transfer count. This may not be appilicable
|
||||
/// for certain scanning modes.
|
||||
/// </summary>
|
||||
/// <value>The pending count.</value>
|
||||
public int PendingTransferCount { get; private set; }
|
||||
|
||||
TW_IMAGEINFO? _imgInfo;
|
||||
/// <summary>
|
||||
/// Gets the tentative image information for the current transfer if applicable.
|
||||
/// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The image info.
|
||||
/// </value>
|
||||
public TW_IMAGEINFO? PendingImageInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_imgInfo.HasValue)
|
||||
{
|
||||
TW_IMAGEINFO img = default;
|
||||
if (DataSource.Session.DGImage.ImageInfo.Get(ref img) == ReturnCode.Success)
|
||||
{
|
||||
_imgInfo = img;
|
||||
}
|
||||
}
|
||||
return _imgInfo;
|
||||
}
|
||||
}
|
||||
|
||||
TW_AUDIOINFO? _audInfo;
|
||||
/// <summary>
|
||||
/// Gets the audio information for the current transfer if applicable.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The audio information.
|
||||
/// </value>
|
||||
public TW_AUDIOINFO? AudioInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_audInfo == null)
|
||||
{
|
||||
TW_AUDIOINFO aud = default;
|
||||
if (DataSource.Session.DGAudio.AudioInfo.Get(ref aud) == ReturnCode.Success)
|
||||
{
|
||||
_audInfo = aud;
|
||||
}
|
||||
}
|
||||
return _audInfo;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains TWAIN codes and source status when an error is encountered during transfer.
|
||||
/// </summary>
|
||||
public class TransferErrorEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransferErrorEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="error">The error.</param>
|
||||
public TransferErrorEventArgs(Exception error)
|
||||
{
|
||||
Exception = error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransferErrorEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <param name="status">The status.</param>
|
||||
public TransferErrorEventArgs(ReturnCode code, TW_STATUS status)
|
||||
{
|
||||
ReturnCode = code;
|
||||
SourceStatus = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the return code from the transfer.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The return code.
|
||||
/// </value>
|
||||
public ReturnCode ReturnCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source status.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The source status.
|
||||
/// </value>
|
||||
public TW_STATUS SourceStatus { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception if the error is from some exception.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The exception.
|
||||
/// </value>
|
||||
public Exception Exception { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ namespace NTwain
|
||||
ModalUI = (ushort)(modal ? 1 : 0),
|
||||
hParent = windowHandle
|
||||
};
|
||||
Session._disableDSNow = false;
|
||||
var rc = Session.DGControl.UserInterface.EnableDSUIOnly(ref ui);
|
||||
if (rc == ReturnCode.Success)
|
||||
{
|
||||
@@ -71,6 +72,7 @@ namespace NTwain
|
||||
ModalUI = (ushort)(modal ? 1 : 0),
|
||||
hParent = windowHandle
|
||||
};
|
||||
Session._disableDSNow = false;
|
||||
var rc = Session.DGControl.UserInterface.EnableDS(ref ui);
|
||||
if (rc == ReturnCode.Success)
|
||||
{
|
||||
|
@@ -37,9 +37,4 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Triplets\Image\" />
|
||||
<Folder Include="Triplets\Audio\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
38
src/NTwain/Triplets/Audio/AudioInfo.cs
Normal file
38
src/NTwain/Triplets/Audio/AudioInfo.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Internals;
|
||||
|
||||
namespace NTwain.Triplets.Audio
|
||||
{
|
||||
sealed class AudioInfo : BaseTriplet
|
||||
{
|
||||
internal AudioInfo(TwainSession session) : base(session) { }
|
||||
|
||||
public ReturnCode Get(ref TW_AUDIOINFO info)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Audio, DataArgumentType.AudioInfo, Message.Get, ref info);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
}
|
||||
}
|
149
src/NTwain/Triplets/Control/PendingXfers.cs
Normal file
149
src/NTwain/Triplets/Control/PendingXfers.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Internals;
|
||||
|
||||
namespace NTwain.Triplets
|
||||
{
|
||||
sealed class PendingXfers : BaseTriplet
|
||||
{
|
||||
internal PendingXfers(TwainSession session) : base(session) { }
|
||||
|
||||
/// <summary>
|
||||
/// This triplet is used to cancel or terminate a transfer. Issued in state 6, this triplet cancels the next
|
||||
/// pending transfer, discards the transfer data, and decrements the pending transfers count. In
|
||||
/// state 7, this triplet terminates the current transfer. If any data has not been transferred (this is
|
||||
/// only possible during a memory transfer) that data is discarded.
|
||||
/// </summary>
|
||||
/// <param name="pendingXfers">The pending xfers.</param>
|
||||
/// <returns></returns>
|
||||
internal ReturnCode EndXfer(TW_PENDINGXFERS pendingXfers)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.EndXfer, ref pendingXfers);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of transfers the Source is ready to supply to the application, upon demand.
|
||||
/// If DAT_XFERGROUP is set to DG_Image, this is the number of images. If DAT_XFERGROUP is set
|
||||
/// to DG_AUDIO, this is the number of audio snippets for the current image. If there is no current
|
||||
/// image, this call must return Failure / SeqError.
|
||||
/// </summary>
|
||||
/// <param name="pendingXfers">The pending xfers.</param>
|
||||
/// <returns></returns>
|
||||
public ReturnCode Get(TW_PENDINGXFERS pendingXfers)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Get, ref pendingXfers);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the number of pending transfers in the Source to zero.
|
||||
/// </summary>
|
||||
/// <param name="pendingXfers">The pending xfers.</param>
|
||||
/// <returns></returns>
|
||||
internal ReturnCode Reset(TW_PENDINGXFERS pendingXfers)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset, ref pendingXfers);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If CapAutoScan is TRUE, this command will stop the operation of the scanner’s automatic
|
||||
/// feeder. No other action is taken.
|
||||
/// </summary>
|
||||
/// <param name="pendingXfers">The pending xfers.</param>
|
||||
/// <returns></returns>
|
||||
public ReturnCode StopFeeder(TW_PENDINGXFERS pendingXfers)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder, ref pendingXfers);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Triplets.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -12,6 +13,8 @@ namespace NTwain.Triplets
|
||||
public partial class DGAudio : BaseTriplet
|
||||
{
|
||||
internal DGAudio(TwainSession session) : base(session) { }
|
||||
|
||||
|
||||
AudioInfo _info;
|
||||
internal AudioInfo AudioInfo => _info ?? (_info = new AudioInfo(Session));
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,9 @@ namespace NTwain.Triplets
|
||||
Event _event;
|
||||
internal Event Event => _event ?? (_event = new Event(Session));
|
||||
|
||||
PendingXfers _pending;
|
||||
internal PendingXfers PendingXfers => _pending ?? (_pending = new PendingXfers(Session));
|
||||
|
||||
XferGroup _xferGroup;
|
||||
/// <summary>
|
||||
/// Gets the operations defined for DAT_XFERGROUP.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Triplets.Image;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -13,5 +14,7 @@ namespace NTwain.Triplets
|
||||
{
|
||||
internal DGImage(TwainSession session) : base(session) { }
|
||||
|
||||
ImageInfo _info;
|
||||
internal ImageInfo ImageInfo => _info ?? (_info = new ImageInfo(Session));
|
||||
}
|
||||
}
|
||||
|
38
src/NTwain/Triplets/Image/ImageInfo.cs
Normal file
38
src/NTwain/Triplets/Image/ImageInfo.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Internals;
|
||||
|
||||
namespace NTwain.Triplets.Image
|
||||
{
|
||||
sealed class ImageInfo : BaseTriplet
|
||||
{
|
||||
internal ImageInfo(TwainSession session) : base(session) { }
|
||||
|
||||
public ReturnCode Get(ref TW_IMAGEINFO info)
|
||||
{
|
||||
if (Is32Bit)
|
||||
{
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
}
|
||||
|
||||
if (IsWin)
|
||||
return NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
if (IsLinux)
|
||||
return NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
if (IsMac)
|
||||
return NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32,
|
||||
DataGroups.Image, DataArgumentType.ImageInfo, Message.Get, ref info);
|
||||
|
||||
return ReturnCode.Failure;
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,6 +15,15 @@ namespace NTwain
|
||||
partial class TwainSession
|
||||
{
|
||||
internal TW_USERINTERFACE _lastEnableUI;
|
||||
internal bool _disableDSNow;
|
||||
|
||||
ReturnCode Handle32BitCallback(TW_IDENTITY origin, TW_IDENTITY destination,
|
||||
DataGroups dg, DataArgumentType dat, Message msg, IntPtr data)
|
||||
{
|
||||
Debug.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId}: {nameof(Handle32BitCallback)}({dg}, {dat}, {msg}, {data})");
|
||||
HandleSourceMsg(msg);
|
||||
return ReturnCode.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If on Windows pass all messages from WndProc here to handle it
|
||||
@@ -76,7 +85,15 @@ namespace NTwain
|
||||
DoTransferRoutine();
|
||||
break;
|
||||
case Message.CloseDSReq:
|
||||
DGControl.UserInterface.DisableDS(ref _lastEnableUI, false);
|
||||
if (_state > TwainState.S5)
|
||||
{
|
||||
// do it after end of current xfer routine.
|
||||
_disableDSNow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DGControl.UserInterface.DisableDS(ref _lastEnableUI, false);
|
||||
}
|
||||
break;
|
||||
case Message.CloseDSOK:
|
||||
DGControl.UserInterface.DisableDS(ref _lastEnableUI, true);
|
||||
@@ -85,8 +102,168 @@ namespace NTwain
|
||||
}
|
||||
|
||||
private void DoTransferRoutine()
|
||||
{
|
||||
var xMech = GetTransferMechs();
|
||||
|
||||
TW_PENDINGXFERS pending = default;
|
||||
var rc = DGControl.PendingXfers.Get(pending);
|
||||
if (rc == ReturnCode.Success)
|
||||
{
|
||||
do
|
||||
{
|
||||
var readyArgs = new TransferReadyEventArgs(CurrentSource, pending.Count, pending.EndOfJob)
|
||||
{
|
||||
CancelAll = _disableDSNow
|
||||
};
|
||||
OnTransferReady(readyArgs);
|
||||
|
||||
|
||||
#region actually handle xfer
|
||||
|
||||
if (readyArgs.CancelAll || _disableDSNow)
|
||||
{
|
||||
rc = DGControl.PendingXfers.Reset(pending);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!readyArgs.CancelCurrent)
|
||||
{
|
||||
if (xMech.ImageMech.HasValue)
|
||||
{
|
||||
switch (xMech.ImageMech.Value)
|
||||
{
|
||||
case XferMech.Memory:
|
||||
rc = DoImageMemoryXfer();
|
||||
break;
|
||||
case XferMech.File:
|
||||
rc = DoImageFileXfer();
|
||||
break;
|
||||
case XferMech.MemFile:
|
||||
rc = DoImageMemoryFileXfer();
|
||||
break;
|
||||
case XferMech.Native:
|
||||
default: // always assume native
|
||||
rc = DoImageNativeXfer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xMech.AudioMech.HasValue)
|
||||
{
|
||||
switch (xMech.AudioMech.Value)
|
||||
{
|
||||
case XferMech.File:
|
||||
rc = DoAudioFileXfer();
|
||||
break;
|
||||
case XferMech.Native:
|
||||
default: // always assume native
|
||||
rc = DoAudioNativeXfer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != ReturnCode.Success)// && StopOnTransferError)
|
||||
{
|
||||
// end xfer without setting rc to exit (good/bad?)
|
||||
DGControl.PendingXfers.Reset(pending);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = DGControl.PendingXfers.EndXfer(pending);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
} while (rc == ReturnCode.Success && pending.Count != 0 && !_disableDSNow);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleXferReturnCode(rc);
|
||||
}
|
||||
|
||||
if (_disableDSNow)
|
||||
{
|
||||
DGControl.UserInterface.DisableDS(ref _lastEnableUI, false);
|
||||
}
|
||||
}
|
||||
|
||||
private ReturnCode DoImageNativeXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ReturnCode DoImageMemoryFileXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ReturnCode DoImageFileXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ReturnCode DoImageMemoryXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ReturnCode DoAudioNativeXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ReturnCode DoAudioFileXfer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void HandleXferReturnCode(ReturnCode rc)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case ReturnCode.Success:
|
||||
case ReturnCode.XferDone:
|
||||
case ReturnCode.Cancel:
|
||||
// ok to keep going
|
||||
break;
|
||||
default:
|
||||
var status = CurrentSource.GetStatus();
|
||||
OnTransferError(new TransferErrorEventArgs(rc, status));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TransferMechs GetTransferMechs()
|
||||
{
|
||||
TransferMechs retVal = default;
|
||||
bool xferImage = true; // default to always xfer image
|
||||
bool xferAudio = false;
|
||||
DataGroups xferGroup = DataGroups.None;
|
||||
XferMech imgXferMech = XferMech.Native;
|
||||
XferMech audXferMech = XferMech.Native;
|
||||
if (DGControl.XferGroup.Get(ref xferGroup) == ReturnCode.Success)
|
||||
{
|
||||
xferAudio = (xferGroup & DataGroups.Audio) == DataGroups.Audio;
|
||||
// some DS returns none but we will assume it's image
|
||||
xferImage = xferGroup == DataGroups.None || (xferGroup & DataGroups.Image) == DataGroups.Image;
|
||||
}
|
||||
if (xferImage)
|
||||
{
|
||||
//imgXferMech = CurrentSource.Capabilities.ICapXferMech.GetCurrent();
|
||||
retVal.ImageMech = imgXferMech;
|
||||
}
|
||||
if (xferAudio)
|
||||
{
|
||||
//audXferMech = CurrentSource.Capabilities.ACapXferMech.GetCurrent();
|
||||
retVal.AudioMech = audXferMech;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
struct TransferMechs
|
||||
{
|
||||
public XferMech? ImageMech;
|
||||
public XferMech? AudioMech;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -77,6 +77,40 @@ namespace NTwain
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a data transfer is ready.
|
||||
/// </summary>
|
||||
public event EventHandler<TransferReadyEventArgs> TransferReady;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="TransferReady"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnTransferReady(TransferReadyEventArgs e)
|
||||
{
|
||||
var handler = TransferReady;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// Occurs when data has been transferred.
|
||||
///// </summary>
|
||||
//public event EventHandler<DataTransferredEventArgs> DataTransferred;
|
||||
/// <summary>
|
||||
/// Occurs when an error has been encountered during transfer.
|
||||
/// </summary>
|
||||
public event EventHandler<TransferErrorEventArgs> TransferError;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="TransferError"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnTransferError(TransferErrorEventArgs e)
|
||||
{
|
||||
var handler = TransferError;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -223,14 +223,6 @@ namespace NTwain
|
||||
return source;
|
||||
}
|
||||
|
||||
ReturnCode Handle32BitCallback(TW_IDENTITY origin, TW_IDENTITY destination,
|
||||
DataGroups dg, DataArgumentType dat, Message msg, IntPtr data)
|
||||
{
|
||||
Debug.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId}: {nameof(Handle32BitCallback)}({dg}, {dat}, {msg}, {data})");
|
||||
HandleSourceMsg(msg);
|
||||
return ReturnCode.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
|
Reference in New Issue
Block a user