From 668066cd2b4061a013ae89d7896481f14da5ec85 Mon Sep 17 00:00:00 2001 From: Eugene Wang <8755753+soukoku@users.noreply.github.com> Date: Sat, 8 Apr 2023 07:03:30 -0400 Subject: [PATCH] Progress in file xfers. --- src/NTwain/DataTransferredEventArgs.cs | 73 ++++++++++++++----------- src/NTwain/TwainAppSession.Xfers.cs | 74 ++++++++++++++++++++------ 2 files changed, 100 insertions(+), 47 deletions(-) diff --git a/src/NTwain/DataTransferredEventArgs.cs b/src/NTwain/DataTransferredEventArgs.cs index bf2da74..a80cd05 100644 --- a/src/NTwain/DataTransferredEventArgs.cs +++ b/src/NTwain/DataTransferredEventArgs.cs @@ -3,61 +3,72 @@ using System; namespace NTwain { - // TODO: a 2-level dispose with end of event method - // and manual dispose for perf if this is not good enough. + // TODO: maybe a 2-level "dispose" with end of event being 1 + // and manual dispose 2 for perf if this is not good enough. public class DataTransferredEventArgs : EventArgs { - readonly TwainAppSession _twain; - readonly bool _isImage; - - - internal DataTransferredEventArgs(TwainAppSession twain, bool isImage, TW_SETUPFILEXFER xfer) + public DataTransferredEventArgs(TW_AUDIOINFO info, TW_SETUPFILEXFER xfer) { - _twain = twain; - _isImage = isImage; + AudioInfo = info; File = xfer; + IsFile = true; } - - /// - /// Ctor for array data; - /// - /// - /// - /// - internal DataTransferredEventArgs(TwainAppSession twain, bool isImage, byte[] data) + public DataTransferredEventArgs(TW_AUDIOINFO info, byte[] data) { - _twain = twain; - _isImage = isImage; + AudioInfo = info; 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; + } /// - /// The complete file data if the transfer was done - /// through memory. IMPORTANT: The data held + /// Whether transferred data is an image or audio. + /// + public bool IsImage { get; } + + /// + /// Whether transfer was a file or memory data. + /// + public bool IsFile { get; } + + + /// + /// The complete file data if is false. + /// IMPORTANT: The data held /// in this array will no longer be valid once /// the event handler ends. /// public byte[]? Data { get; } /// - /// The file info if this was a file transfer. + /// The file info if is true. /// public TW_SETUPFILEXFER? File { get; } /// - /// Gets the final image information if transfer was an image. + /// Gets the final image information if is true. /// - public TW_IMAGEINFO? GetImageInfo() - { - if (_isImage && _twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS) - { - return info; - } - return null; + public TW_IMAGEINFO ImageInfo { get; } + + + /// + /// Gets the final audio information if is false. + /// + public TW_AUDIOINFO AudioInfo { get; } - } } } \ No newline at end of file diff --git a/src/NTwain/TwainAppSession.Xfers.cs b/src/NTwain/TwainAppSession.Xfers.cs index 75e2804..7efa6f7 100644 --- a/src/NTwain/TwainAppSession.Xfers.cs +++ b/src/NTwain/TwainAppSession.Xfers.cs @@ -32,6 +32,9 @@ namespace NTwain /// 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 bool xferImage = true; bool xferAudio = false; @@ -77,7 +80,7 @@ namespace NTwain if (readyArgs.Cancel == CancelType.EndNow || _closeDsRequested) { 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; } if (readyArgs.Cancel == CancelType.Graceful) @@ -143,24 +146,56 @@ namespace NTwain HandleNonSuccessXferCode(sts); } - //if (State > STATE.S5) - //{ - //if (_closeDsRequested) - //{ - _uiThreadMarshaller.BeginInvoke(() => + if (State >= STATE.S5) { - DisableSource(); - }); - //} + _uiThreadMarshaller.BeginInvoke(() => + { + DisableSource(); + }); + } } 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() { + 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; } @@ -179,7 +214,7 @@ namespace NTwain STS sts = default; try { - // assuming user already configured the transfer in transferready event + // 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 @@ -187,10 +222,10 @@ namespace NTwain if (sts.RC == TWRC.XFERDONE) { State = STATE.S7; - try { - var args = new DataTransferredEventArgs(this, true, xfer); + GetImageInfo(out TW_IMAGEINFO info); + var args = new DataTransferredEventArgs(info, xfer); DataTransferred?.Invoke(this, args); } catch { } @@ -236,12 +271,18 @@ namespace NTwain { data = ImageTools.GetTiffData(XferMemPool, lockedPtr); } + else + { + // PicHandle? + // don't support more formats :( + } if (data != null) { try { - var args = new DataTransferredEventArgs(this, true, data); + GetImageInfo(out TW_IMAGEINFO info); + var args = new DataTransferredEventArgs(info, data); DataTransferred?.Invoke(this, args); } catch { } @@ -266,13 +307,14 @@ namespace NTwain } finally { - State = STATE.S6; if (lockedPtr != IntPtr.Zero) Unlock(dataPtr); if (dataPtr != IntPtr.Zero) Free(dataPtr); } return sts; } + + // TODO: this is currently not handled in the right place private void HandleNonSuccessXferCode(STS sts) { switch (sts.RC) @@ -281,7 +323,7 @@ namespace NTwain case TWRC.XFERDONE: // ok to keep going break; - case TWRC.CANCEL: + case TWRC.CANCEL: TW_PENDINGXFERS pending = default; DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending); break;