Progress in file xfers.

This commit is contained in:
Eugene Wang 2023-04-08 07:03:30 -04:00
parent 443419ff64
commit 668066cd2b
2 changed files with 100 additions and 47 deletions

View File

@ -3,61 +3,72 @@ using System;
namespace NTwain namespace NTwain
{ {
// TODO: a 2-level dispose with end of event method // TODO: maybe a 2-level "dispose" with end of event being 1
// and manual dispose for perf if this is not good enough. // and manual dispose 2 for perf if this is not good enough.
public class DataTransferredEventArgs : EventArgs public class DataTransferredEventArgs : EventArgs
{ {
readonly TwainAppSession _twain; public DataTransferredEventArgs(TW_AUDIOINFO info, TW_SETUPFILEXFER xfer)
readonly bool _isImage;
internal DataTransferredEventArgs(TwainAppSession twain, bool isImage, TW_SETUPFILEXFER xfer)
{ {
_twain = twain; AudioInfo = info;
_isImage = isImage;
File = xfer; File = xfer;
IsFile = true;
} }
public DataTransferredEventArgs(TW_AUDIOINFO info, byte[] data)
/// <summary>
/// Ctor for array data;
/// </summary>
/// <param name="twain"></param>
/// <param name="isImage"></param>
/// <param name="data"></param>
internal DataTransferredEventArgs(TwainAppSession twain, bool isImage, byte[] data)
{ {
_twain = twain; AudioInfo = info;
_isImage = isImage;
Data = data; Data = data;
} }
public DataTransferredEventArgs(TW_IMAGEINFO info, TW_SETUPFILEXFER xfer)
{
ImageInfo = info;
File = xfer;
IsImage = true;
IsFile = true;
}
public DataTransferredEventArgs(TW_IMAGEINFO info, byte[] data)
{
ImageInfo = info;
Data = data;
IsImage = true;
}
/// <summary> /// <summary>
/// The complete file data if the transfer was done /// Whether transferred data is an image or audio.
/// through memory. IMPORTANT: The data held /// </summary>
public bool IsImage { get; }
/// <summary>
/// Whether transfer was a file or memory data.
/// </summary>
public bool IsFile { get; }
/// <summary>
/// The complete file data if <see cref="IsFile"/> is false.
/// IMPORTANT: The data held
/// in this array will no longer be valid once /// in this array will no longer be valid once
/// the event handler ends. /// the event handler ends.
/// </summary> /// </summary>
public byte[]? Data { get; } public byte[]? Data { get; }
/// <summary> /// <summary>
/// The file info if this was a file transfer. /// The file info if <see cref="IsFile"/> is true.
/// </summary> /// </summary>
public TW_SETUPFILEXFER? File { get; } public TW_SETUPFILEXFER? File { get; }
/// <summary> /// <summary>
/// Gets the final image information if transfer was an image. /// Gets the final image information if <see cref="IsImage"/> is true.
/// </summary> /// </summary>
public TW_IMAGEINFO? GetImageInfo() public TW_IMAGEINFO ImageInfo { get; }
{
if (_isImage && _twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS)
{ /// <summary>
return info; /// Gets the final audio information if <see cref="IsImage"/> is false.
} /// </summary>
return null; public TW_AUDIOINFO AudioInfo { get; }
}
} }
} }

View File

@ -32,6 +32,9 @@ namespace NTwain
/// </summary> /// </summary>
void EnterTransferRoutine() void EnterTransferRoutine()
{ {
// TODO: currently implemented routine doesn't quite work for audio as described in spec
// default options if source doesn't support changing them or whatever // default options if source doesn't support changing them or whatever
bool xferImage = true; bool xferImage = true;
bool xferAudio = false; bool xferAudio = false;
@ -77,7 +80,7 @@ namespace NTwain
if (readyArgs.Cancel == CancelType.EndNow || _closeDsRequested) if (readyArgs.Cancel == CancelType.EndNow || _closeDsRequested)
{ {
sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending)); sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending));
if (sts.RC == TWRC.SUCCESS) State = STATE.S5; if (sts.RC == TWRC.SUCCESS && xferImage) State = STATE.S5;
break; break;
} }
if (readyArgs.Cancel == CancelType.Graceful) if (readyArgs.Cancel == CancelType.Graceful)
@ -143,24 +146,56 @@ namespace NTwain
HandleNonSuccessXferCode(sts); HandleNonSuccessXferCode(sts);
} }
//if (State > STATE.S5) if (State >= STATE.S5)
//{
//if (_closeDsRequested)
//{
_uiThreadMarshaller.BeginInvoke(() =>
{ {
DisableSource(); _uiThreadMarshaller.BeginInvoke(() =>
}); {
//} DisableSource();
});
}
} }
private STS TransferFileAudio() private STS TransferFileAudio()
{ {
return default; STS sts = default;
try
{
// assuming user already configured the transfer in transferready event,
// get what will be transferred
DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER xfer);
// and just start it
sts = WrapInSTS(DGAudio.AudioFileXfer.Get(ref _appIdentity, ref _currentDS));
if (sts.RC == TWRC.XFERDONE)
{
State = STATE.S7;
try
{
DGAudio.AudioInfo.Get(ref _appIdentity, ref _currentDS, out TW_AUDIOINFO info);
var args = new DataTransferredEventArgs(info, xfer);
DataTransferred?.Invoke(this, args);
}
catch { }
}
else
{
HandleNonSuccessXferCode(sts);
}
}
catch (Exception ex)
{
try
{
TransferError?.Invoke(this, new TransferErrorEventArgs(ex));
}
catch { }
}
return sts;
} }
private STS TransferNativeAudio() private STS TransferNativeAudio()
{ {
DGAudio.AudioInfo.Get(ref _appIdentity, ref _currentDS, out TW_AUDIOINFO info);
// ugh don't know how to read wav/aiff from pointer yet
return default; return default;
} }
@ -179,7 +214,7 @@ namespace NTwain
STS sts = default; STS sts = default;
try try
{ {
// assuming user already configured the transfer in transferready event // assuming user already configured the transfer in transferready event,
// get what will be transferred // get what will be transferred
DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER xfer); DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER xfer);
// and just start it // and just start it
@ -187,10 +222,10 @@ namespace NTwain
if (sts.RC == TWRC.XFERDONE) if (sts.RC == TWRC.XFERDONE)
{ {
State = STATE.S7; State = STATE.S7;
try try
{ {
var args = new DataTransferredEventArgs(this, true, xfer); GetImageInfo(out TW_IMAGEINFO info);
var args = new DataTransferredEventArgs(info, xfer);
DataTransferred?.Invoke(this, args); DataTransferred?.Invoke(this, args);
} }
catch { } catch { }
@ -236,12 +271,18 @@ namespace NTwain
{ {
data = ImageTools.GetTiffData(XferMemPool, lockedPtr); data = ImageTools.GetTiffData(XferMemPool, lockedPtr);
} }
else
{
// PicHandle?
// don't support more formats :(
}
if (data != null) if (data != null)
{ {
try try
{ {
var args = new DataTransferredEventArgs(this, true, data); GetImageInfo(out TW_IMAGEINFO info);
var args = new DataTransferredEventArgs(info, data);
DataTransferred?.Invoke(this, args); DataTransferred?.Invoke(this, args);
} }
catch { } catch { }
@ -266,13 +307,14 @@ namespace NTwain
} }
finally finally
{ {
State = STATE.S6;
if (lockedPtr != IntPtr.Zero) Unlock(dataPtr); if (lockedPtr != IntPtr.Zero) Unlock(dataPtr);
if (dataPtr != IntPtr.Zero) Free(dataPtr); if (dataPtr != IntPtr.Zero) Free(dataPtr);
} }
return sts; return sts;
} }
// TODO: this is currently not handled in the right place
private void HandleNonSuccessXferCode(STS sts) private void HandleNonSuccessXferCode(STS sts)
{ {
switch (sts.RC) switch (sts.RC)
@ -281,7 +323,7 @@ namespace NTwain
case TWRC.XFERDONE: case TWRC.XFERDONE:
// ok to keep going // ok to keep going
break; break;
case TWRC.CANCEL: case TWRC.CANCEL:
TW_PENDINGXFERS pending = default; TW_PENDINGXFERS pending = default;
DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending); DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending);
break; break;