diff --git a/samples/WinForm32/Form1.cs b/samples/WinForm32/Form1.cs index 1243f30..63c2bb4 100644 --- a/samples/WinForm32/Form1.cs +++ b/samples/WinForm32/Form1.cs @@ -39,7 +39,7 @@ namespace WinFormSample lblCurrent.Text = ds.ProductName; if (twain.State == STATE.S4) { - var caps = twain.GetAllCaps(); + twain.GetCapValues(CAP.CAP_SUPPORTEDCAPS, out IList caps); foreach (var c in caps) listCaps.Items.Add(c); diff --git a/src/NTwain/Data/ValueReader.cs b/src/NTwain/Data/ValueReader.cs index ecfca3e..b4fb2dd 100644 --- a/src/NTwain/Data/ValueReader.cs +++ b/src/NTwain/Data/ValueReader.cs @@ -9,7 +9,7 @@ namespace NTwain.Data /// /// Contains methods for reading pointers into various things. /// - static class ValueReader + public static class ValueReader { /// /// Reads pointer as UTF8 string. diff --git a/src/NTwain/TwainAppSession.Caps.cs b/src/NTwain/TwainAppSession.Caps.cs index bce9020..789ea38 100644 --- a/src/NTwain/TwainAppSession.Caps.cs +++ b/src/NTwain/TwainAppSession.Caps.cs @@ -11,20 +11,20 @@ namespace NTwain partial class TwainAppSession { - /// - /// Gets all the supported caps for the current source. - /// - /// - public IList GetAllCaps() - { - // just as a sample of how to read cap values + ///// + ///// Gets all the supported caps for the current source. + ///// + ///// + //public IList GetAllCaps() + //{ + // // just as a sample of how to read cap values - if (GetCapValues(CAP.CAP_SUPPORTEDCAPS, out TW_CAPABILITY value).RC == TWRC.SUCCESS) - { - return value.ReadArray(this); - } - return Array.Empty(); - } + // if (GetCapValues(CAP.CAP_SUPPORTEDCAPS, out TW_CAPABILITY value).RC == TWRC.SUCCESS) + // { + // return value.ReadArray(this); + // } + // return Array.Empty(); + //} /// /// Gets a CAP's actual supported operations. @@ -43,8 +43,8 @@ namespace NTwain } /// - /// Gets a CAP's current value. - /// Caller will need to free the memory. + /// Gets a CAP's raw current value. + /// Caller will need to manually read and free the memory. /// /// /// @@ -56,8 +56,49 @@ namespace NTwain } /// - /// Gets a CAP's default value. - /// Caller will need to free the memory. + /// Gets a CAP's current value. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapCurrent(CAP cap, out TValue value) where TValue : struct + { + value = default; + var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + value = twcap.ReadOneValue(this); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(this); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value = twenum.Items[twenum.CurrentIndex]; + } + break; + case TWON.RANGE: + value = twcap.ReadRange(this).CurrentValue; + break; + case TWON.ARRAY: + // no source should ever return an array but anyway + var twarr = twcap.ReadArray(this); + if (twarr != null && twarr.Count > 0) value = twarr[0]; + break; + default: + twcap.Free(this); break; + } + } + return sts; + } + + /// + /// Gets a CAP's raw default value. + /// Caller will need to manually read and free the memory. /// /// /// @@ -68,9 +109,51 @@ namespace NTwain return WrapInSTS(DGControl.Capability.GetDefault(ref _appIdentity, ref _currentDS, ref value)); } + /// - /// Gets a CAP's supported values. - /// Caller will need to free the memory. + /// Gets a CAP's default value. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapDefault(CAP cap, out TValue value) where TValue : struct + { + value = default; + var sts = GetCapDefault(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + value = twcap.ReadOneValue(this); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(this); + if (twenum.Items != null && twenum.DefaultIndex < twenum.Items.Length) + { + value = twenum.Items[twenum.DefaultIndex]; + } + break; + case TWON.RANGE: + value = twcap.ReadRange(this).DefaultValue; + break; + case TWON.ARRAY: + // no source should ever return an array but anyway + var twarr = twcap.ReadArray(this); + if (twarr != null && twarr.Count > 0) value = twarr[0]; + break; + default: + twcap.Free(this); break; + } + } + return sts; + } + + /// + /// Gets a CAP's raw supported values. + /// Caller will need to manually read and free the memory. /// /// /// @@ -81,9 +164,51 @@ namespace NTwain return WrapInSTS(DGControl.Capability.Get(ref _appIdentity, ref _currentDS, ref value)); } + + /// + /// Gets a CAP's supported values. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapValues(CAP cap, out IList values) where TValue : struct + { + values = new List(); + var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + values.Add(twcap.ReadOneValue(this)); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(this); + if (twenum.Items != null && twenum.Items.Length > 0) + ((List)values).AddRange(twenum.Items); + break; + case TWON.RANGE: + // This can be slow + var twrange = twcap.ReadRange(this); + ((List)values).AddRange(twrange); + break; + case TWON.ARRAY: + var twarr = twcap.ReadArray(this); + if (twarr != null && twarr.Count > 0) + ((List)values).AddRange(twarr); + break; + default: + twcap.Free(this); break; + } + } + return sts; + } + /// /// Gets a CAP's help text (description). - /// This is not implemented. + /// This is not implemented due to unclear spec. /// /// /// @@ -95,7 +220,7 @@ namespace NTwain var rc = DGControl.Capability.GetHelp(ref _appIdentity, ref _currentDS, ref value); if (rc == TWRC.SUCCESS) { - // how to determine the length of this thing??? + // TODO: how to determine the length of this thing??? var data = value.ReadOneValue(this, false); } value.Free(this); @@ -104,7 +229,7 @@ namespace NTwain /// /// Gets a CAP's text name label. - /// This is not implemented. + /// This is not implemented due to unclear spec. /// /// /// @@ -116,7 +241,7 @@ namespace NTwain var rc = DGControl.Capability.GetLabel(ref _appIdentity, ref _currentDS, ref value); if (rc == TWRC.SUCCESS) { - // how to determine the length of this thing??? + // TODO: how to determine the length of this thing??? var data = value.ReadOneValue(this, false); } value.Free(this); @@ -124,7 +249,7 @@ namespace NTwain } /// - /// Gets a CAP's value label texts. + /// Gets a CAP's enum/array value label texts. /// /// /// @@ -145,6 +270,7 @@ namespace NTwain /// /// Sets a CAP's current value. + /// Memory of the value will be freed afterwards. /// /// /// @@ -163,6 +289,7 @@ namespace NTwain /// /// Sets a CAP's constraint values. + /// Memory of the value will be freed afterwards. /// /// /// @@ -175,7 +302,7 @@ namespace NTwain /// /// Resets a CAP's current value to power-on default. - /// Caller will need to free the memory. + /// Caller will need to manually read and free the memory. /// /// /// @@ -193,12 +320,52 @@ namespace NTwain return WrapInSTS(rc); } + /// + /// Resets a CAP's current value to power-on default. + /// + /// + /// + /// + /// + public STS ResetCap(CAP cap, out TValue value) where TValue : struct + { + value = default; + var sts = ResetCap(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + value = twcap.ReadOneValue(this); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(this); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value = twenum.Items[twenum.CurrentIndex]; + } + break; + case TWON.RANGE: + value = twcap.ReadRange(this).CurrentValue; + break; + case TWON.ARRAY: + var twarr = twcap.ReadArray(this); + if (twarr != null && twarr.Count > 0) value = twarr[0]; + break; + default: + twcap.Free(this); break; + } + } + return sts; + } + /// /// Resets all CAP values and constraint to power-on defaults. /// /// public STS ResetAllCaps() { + // no memory is allocated for this var value = new TW_CAPABILITY(CAP.CAP_SUPPORTEDCAPS); var rc = DGControl.Capability.ResetAll(ref _appIdentity, ref _currentDS, ref value); @@ -212,10 +379,9 @@ namespace NTwain private void RefreshCapLanguage() { - var rc2 = GetCapCurrent(CAP.CAP_LANGUAGE, out TW_CAPABILITY curCap); + var rc2 = GetCapCurrent(CAP.CAP_LANGUAGE, out TWLG lang); if (rc2.RC == TWRC.SUCCESS) { - var lang = curCap.ReadOneValue(this); Language.Set(lang); } } diff --git a/src/NTwain/TwainAppSession.Xfers.cs b/src/NTwain/TwainAppSession.Xfers.cs index 933ee6d..adcea01 100644 --- a/src/NTwain/TwainAppSession.Xfers.cs +++ b/src/NTwain/TwainAppSession.Xfers.cs @@ -16,7 +16,7 @@ namespace NTwain // experiment using array pool for things transferred in memory. // this can pool up to a "normal" max of legal size paper in 24 bit at 300 dpi (~31MB) // so the array max is made with 32 MB. Typical usage should be a lot less. - static readonly ArrayPool XferMemPool = ArrayPool.Create(32505856, 4); + static readonly ArrayPool XferMemPool = ArrayPool.Create(32 * 1024 * 1024, 8); public STS GetImageInfo(out TW_IMAGEINFO info) { @@ -34,8 +34,6 @@ namespace NTwain // default options if source doesn't support changing them or whatever bool xferImage = true; bool xferAudio = false; - var imgXferMech = TWSX.NATIVE; - var audXferMech = TWSX.NATIVE; if (DGControl.XferGroup.Get(ref _appIdentity, ref _currentDS, out DG xferType) == TWRC.SUCCESS) { xferAudio = (xferType & DG.AUDIO) == DG.AUDIO; @@ -54,14 +52,10 @@ namespace NTwain } } - if (xferImage && GetCapCurrent(CAP.ICAP_XFERMECH, out TW_CAPABILITY cap).RC == TWRC.SUCCESS) - { - imgXferMech = cap.ReadOneValue(this); - } - else if (xferAudio && GetCapCurrent(CAP.ACAP_XFERMECH, out cap).RC == TWRC.SUCCESS) - { - audXferMech = cap.ReadOneValue(this); - } + var imgXferMech = TWSX.NATIVE; + var audXferMech = TWSX.NATIVE; + if (xferImage) GetCapCurrent(CAP.ICAP_XFERMECH, out imgXferMech); + else if (xferAudio) GetCapCurrent(CAP.ACAP_XFERMECH, out audXferMech); TW_PENDINGXFERS pending = default; var rc = DGControl.PendingXfers.Get(ref _appIdentity, ref _currentDS, ref pending);