diff --git a/NTwain/ITwainSession.cs b/NTwain/ITwainSession.cs new file mode 100644 index 0000000..862e715 --- /dev/null +++ b/NTwain/ITwainSession.cs @@ -0,0 +1,63 @@ +using NTwain.Data; +using System; +using System.ComponentModel; +namespace NTwain +{ + /// + /// Interface for keeping track of current TWAIN state with current app and source ids. + /// + public interface ITwainSession : INotifyPropertyChanged + { + /// + /// Gets the app id used for the session. + /// + /// The app id. + TWIdentity AppId { get; } + + /// + /// Gets the source id used for the session. + /// + /// The source id. + TWIdentity SourceId { get; } + + /// + /// Gets the current state number as defined by the TWAIN spec. + /// + /// The state. + int State { get; } + } + + /// + /// Internal interface for state management. + /// + interface ITwainSessionInternal : ITwainSession + { + /// + /// Gets or sets a value indicating whether calls to triplets will verify the current twain session state. + /// + /// + /// true if state value is enforced; otherwise, false. + /// + bool EnforceState { get; set; } + + /// + /// Changes the state right away. + /// + /// The new state. + /// if set to true to notify change. + void ChangeState(int newState, bool notifyChange); + + /// + /// Gets the pending state changer and tentatively changes the session state to the specified value. + /// Value will only stick if committed. + /// + /// The new state. + /// + ICommitable GetPendingStateChanger(int newState); + } + + interface ICommitable : IDisposable + { + void Commit(); + } +} diff --git a/NTwain/NTwain.csproj b/NTwain/NTwain.csproj index f095da2..93cb51d 100644 --- a/NTwain/NTwain.csproj +++ b/NTwain/NTwain.csproj @@ -60,6 +60,7 @@ + True diff --git a/NTwain/Properties/VersionInfo.cs b/NTwain/Properties/VersionInfo.cs index d474805..d6fe60d 100644 --- a/NTwain/Properties/VersionInfo.cs +++ b/NTwain/Properties/VersionInfo.cs @@ -14,6 +14,6 @@ namespace NTwain // keep this same in majors releases public const string Release = "0.8.0.0"; // change this for each nuget release - public const string Build = "0.8.0"; + public const string Build = "0.8.1"; } } \ No newline at end of file diff --git a/NTwain/Triplets/DGAudio/DGAudio.AudioFileXfer.cs b/NTwain/Triplets/DGAudio/DGAudio.AudioFileXfer.cs index dbd7366..f344ee2 100644 --- a/NTwain/Triplets/DGAudio/DGAudio.AudioFileXfer.cs +++ b/NTwain/Triplets/DGAudio/DGAudio.AudioFileXfer.cs @@ -5,7 +5,7 @@ namespace NTwain.Triplets { sealed class AudioFileXfer : OpBase { - internal AudioFileXfer(TwainSession session) : base(session) { } + internal AudioFileXfer(ITwainSessionInternal session) : base(session) { } /// /// This operation is used to initiate the transfer of audio from the Source to the application via the /// disk-file transfer mechanism. It causes the transfer to begin. diff --git a/NTwain/Triplets/DGAudio/DGAudio.AudioInfo.cs b/NTwain/Triplets/DGAudio/DGAudio.AudioInfo.cs index 102c1b0..b9e22db 100644 --- a/NTwain/Triplets/DGAudio/DGAudio.AudioInfo.cs +++ b/NTwain/Triplets/DGAudio/DGAudio.AudioInfo.cs @@ -5,7 +5,7 @@ namespace NTwain.Triplets { public sealed class AudioInfo : OpBase { - internal AudioInfo(TwainSession session) : base(session) { } + internal AudioInfo(ITwainSessionInternal session) : base(session) { } /// /// Used to get the information of the current audio data ready to transfer. /// diff --git a/NTwain/Triplets/DGAudio/DGAudio.AudioNativeXfer.cs b/NTwain/Triplets/DGAudio/DGAudio.AudioNativeXfer.cs index bd41a3d..cdd13c0 100644 --- a/NTwain/Triplets/DGAudio/DGAudio.AudioNativeXfer.cs +++ b/NTwain/Triplets/DGAudio/DGAudio.AudioNativeXfer.cs @@ -5,7 +5,7 @@ namespace NTwain.Triplets { sealed class AudioNativeXfer : OpBase { - internal AudioNativeXfer(TwainSession session) : base(session) { } + internal AudioNativeXfer(ITwainSessionInternal session) : base(session) { } /// /// Causes the transfer of an audio data from the Source to the application, via the Native /// transfer mechanism, to begin. The resulting data is stored in main memory in a single block. diff --git a/NTwain/Triplets/DGAudio/DGAudio.cs b/NTwain/Triplets/DGAudio/DGAudio.cs index 19e3158..789c0e7 100644 --- a/NTwain/Triplets/DGAudio/DGAudio.cs +++ b/NTwain/Triplets/DGAudio/DGAudio.cs @@ -6,8 +6,8 @@ namespace NTwain.Triplets /// public sealed class DGAudio { - TwainSession _session; - internal DGAudio(TwainSession session) + ITwainSessionInternal _session; + internal DGAudio(ITwainSessionInternal session) { if (session == null) { throw new ArgumentNullException("session"); } _session = session; diff --git a/NTwain/Triplets/DGControl/DGControl.Callback.cs b/NTwain/Triplets/DGControl/DGControl.Callback.cs index 2d31162..8867ffd 100644 --- a/NTwain/Triplets/DGControl/DGControl.Callback.cs +++ b/NTwain/Triplets/DGControl/DGControl.Callback.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class Callback : OpBase { - internal Callback(TwainSession session) : base(session) { } + internal Callback(ITwainSessionInternal session) : base(session) { } /// /// This triplet is sent to the DSM by the Application to register the application’s entry point with /// the DSM, so that the DSM can use callbacks to inform the application of events generated by the diff --git a/NTwain/Triplets/DGControl/DGControl.Callback2.cs b/NTwain/Triplets/DGControl/DGControl.Callback2.cs index 2749d7c..f0d47d0 100644 --- a/NTwain/Triplets/DGControl/DGControl.Callback2.cs +++ b/NTwain/Triplets/DGControl/DGControl.Callback2.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class Callback2 : OpBase { - internal Callback2(TwainSession session) : base(session) { } + internal Callback2(ITwainSessionInternal session) : base(session) { } /// /// This triplet is sent to the DSM by the Application to register the application’s entry point with /// the DSM, so that the DSM can use callbacks to inform the application of events generated by the diff --git a/NTwain/Triplets/DGControl/DGControl.Capability.cs b/NTwain/Triplets/DGControl/DGControl.Capability.cs index 3109109..15b0f9a 100644 --- a/NTwain/Triplets/DGControl/DGControl.Capability.cs +++ b/NTwain/Triplets/DGControl/DGControl.Capability.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class Capability : OpBase { - internal Capability(TwainSession session) : base(session) { } + internal Capability(ITwainSessionInternal session) : base(session) { } /// /// Returns the Source’s Current, Default and Available Values for a specified capability. /// diff --git a/NTwain/Triplets/DGControl/DGControl.CustomDSData.cs b/NTwain/Triplets/DGControl/DGControl.CustomDSData.cs index b152733..40fa3a4 100644 --- a/NTwain/Triplets/DGControl/DGControl.CustomDSData.cs +++ b/NTwain/Triplets/DGControl/DGControl.CustomDSData.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class CustomDSData : OpBase { - internal CustomDSData(TwainSession session) : base(session) { } + internal CustomDSData(ITwainSessionInternal session) : base(session) { } /// /// This operation is used by the application to query the data source for its current settings, e.g. /// DPI, paper size, color format. The actual format of the data is data source dependent and not diff --git a/NTwain/Triplets/DGControl/DGControl.DeviceEvent.cs b/NTwain/Triplets/DGControl/DGControl.DeviceEvent.cs index 56222b6..b33fb39 100644 --- a/NTwain/Triplets/DGControl/DGControl.DeviceEvent.cs +++ b/NTwain/Triplets/DGControl/DGControl.DeviceEvent.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class DeviceEvent : OpBase { - internal DeviceEvent(TwainSession session) : base(session) { } + internal DeviceEvent(ITwainSessionInternal session) : base(session) { } public ReturnCode Get(out TWDeviceEvent sourceDeviceEvent) { Session.VerifyState(4, 7, DataGroups.Control, DataArgumentType.DeviceEvent, Message.Get); diff --git a/NTwain/Triplets/DGControl/DGControl.EntryPoint.cs b/NTwain/Triplets/DGControl/DGControl.EntryPoint.cs index 0e500d9..0674753 100644 --- a/NTwain/Triplets/DGControl/DGControl.EntryPoint.cs +++ b/NTwain/Triplets/DGControl/DGControl.EntryPoint.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class EntryPoint : OpBase { - internal EntryPoint(TwainSession session) : base(session) { } + internal EntryPoint(ITwainSessionInternal session) : base(session) { } /// /// Gets the function entry points for twain 2.0 or higher. /// diff --git a/NTwain/Triplets/DGControl/DGControl.Event.cs b/NTwain/Triplets/DGControl/DGControl.Event.cs index ff95d42..9342882 100644 --- a/NTwain/Triplets/DGControl/DGControl.Event.cs +++ b/NTwain/Triplets/DGControl/DGControl.Event.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class Event : OpBase { - internal Event(TwainSession session) : base(session) { } + internal Event(ITwainSessionInternal session) : base(session) { } /// /// This operation supports the distribution of events from the application to Sources so that the diff --git a/NTwain/Triplets/DGControl/DGControl.FileSystem.cs b/NTwain/Triplets/DGControl/DGControl.FileSystem.cs index 91c8bc2..eb0b292 100644 --- a/NTwain/Triplets/DGControl/DGControl.FileSystem.cs +++ b/NTwain/Triplets/DGControl/DGControl.FileSystem.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class FileSystem : OpBase { - internal FileSystem(TwainSession session) : base(session) { } + internal FileSystem(ITwainSessionInternal session) : base(session) { } /// /// This operation selects the destination directory within the Source (camera, storage, etc), where /// images captured using CapAutomaticCapture will be stored. This command only selects diff --git a/NTwain/Triplets/DGControl/DGControl.Identity.cs b/NTwain/Triplets/DGControl/DGControl.Identity.cs index ee14587..5441ed6 100644 --- a/NTwain/Triplets/DGControl/DGControl.Identity.cs +++ b/NTwain/Triplets/DGControl/DGControl.Identity.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class Identity : OpBase { - internal Identity(TwainSession session) : base(session) { } + internal Identity(ITwainSessionInternal session) : base(session) { } /// /// When an application is finished with a Source, it must formally close the session between them /// using this operation. This is necessary in case the Source only supports connection with a single @@ -19,8 +19,8 @@ namespace NTwain.Triplets Session.VerifyState(4, 4, DataGroups.Control, DataArgumentType.Identity, Message.CloseDS); var rc = PInvoke.DsmEntry(Session.AppId, Message.CloseDS, Session.SourceId); if (rc == ReturnCode.Success) - { - Session.State = 3; + { + Session.ChangeState(3, true); } return rc; } @@ -74,8 +74,8 @@ namespace NTwain.Triplets Session.VerifyState(3, 3, DataGroups.Control, DataArgumentType.Identity, Message.OpenDS); var rc = PInvoke.DsmEntry(Session.AppId, Message.OpenDS, source); if (rc == ReturnCode.Success) - { - Session.State = 4; + { + Session.ChangeState(4, true); } return rc; } diff --git a/NTwain/Triplets/DGControl/DGControl.Parent.cs b/NTwain/Triplets/DGControl/DGControl.Parent.cs index 7ea598f..3157ef8 100644 --- a/NTwain/Triplets/DGControl/DGControl.Parent.cs +++ b/NTwain/Triplets/DGControl/DGControl.Parent.cs @@ -7,7 +7,7 @@ namespace NTwain.Triplets { sealed class Parent : OpBase { - internal Parent(TwainSession session) : base(session) { } + internal Parent(ITwainSessionInternal session) : base(session) { } /// /// When the application has closed all the Sources it had previously opened, and is finished with @@ -23,7 +23,7 @@ namespace NTwain.Triplets var rc = PInvoke.DsmEntry(Session.AppId, null, DataGroups.Control, DataArgumentType.Parent, Message.CloseDsm, ref handle); if (rc == ReturnCode.Success) { - Session.State = 2; + Session.ChangeState(2, true); } return rc; } @@ -41,7 +41,7 @@ namespace NTwain.Triplets var rc = PInvoke.DsmEntry(Session.AppId, null, DataGroups.Control, DataArgumentType.Parent, Message.OpenDsm, ref handle); if (rc == ReturnCode.Success) { - Session.State = 3; + Session.ChangeState(3, true); } return rc; } diff --git a/NTwain/Triplets/DGControl/DGControl.PassThru.cs b/NTwain/Triplets/DGControl/DGControl.PassThru.cs index 416519d..414d466 100644 --- a/NTwain/Triplets/DGControl/DGControl.PassThru.cs +++ b/NTwain/Triplets/DGControl/DGControl.PassThru.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class PassThru : OpBase { - internal PassThru(TwainSession session) : base(session) { } + internal PassThru(ITwainSessionInternal session) : base(session) { } /// /// PASSTHRU is intended for the use of Source writers writing diagnostic applications. It allows /// raw communication with the currently selected device in the Source. diff --git a/NTwain/Triplets/DGControl/DGControl.PendingXfers.cs b/NTwain/Triplets/DGControl/DGControl.PendingXfers.cs index e275aa8..94f537e 100644 --- a/NTwain/Triplets/DGControl/DGControl.PendingXfers.cs +++ b/NTwain/Triplets/DGControl/DGControl.PendingXfers.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class PendingXfers : OpBase { - internal PendingXfers(TwainSession session) : base(session) { } + internal PendingXfers(ITwainSessionInternal session) : base(session) { } /// /// 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 diff --git a/NTwain/Triplets/DGControl/DGControl.SetupFileXfer.cs b/NTwain/Triplets/DGControl/DGControl.SetupFileXfer.cs index 1a90a95..690d56a 100644 --- a/NTwain/Triplets/DGControl/DGControl.SetupFileXfer.cs +++ b/NTwain/Triplets/DGControl/DGControl.SetupFileXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class SetupFileXfer : OpBase { - internal SetupFileXfer(TwainSession session) : base(session) { } + internal SetupFileXfer(ITwainSessionInternal session) : base(session) { } /// /// Returns information about the file into which the Source has or will put the acquired image /// or audio data. diff --git a/NTwain/Triplets/DGControl/DGControl.SetupMemXfer.cs b/NTwain/Triplets/DGControl/DGControl.SetupMemXfer.cs index 42fca56..c10be6a 100644 --- a/NTwain/Triplets/DGControl/DGControl.SetupMemXfer.cs +++ b/NTwain/Triplets/DGControl/DGControl.SetupMemXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class SetupMemXfer : OpBase { - internal SetupMemXfer(TwainSession session) : base(session) { } + internal SetupMemXfer(ITwainSessionInternal session) : base(session) { } /// /// Returns the Source’s preferred, minimum, and maximum allocation sizes for transfer memory /// buffers. diff --git a/NTwain/Triplets/DGControl/DGControl.Status.cs b/NTwain/Triplets/DGControl/DGControl.Status.cs index c54b869..d6873e5 100644 --- a/NTwain/Triplets/DGControl/DGControl.Status.cs +++ b/NTwain/Triplets/DGControl/DGControl.Status.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class Status : OpBase { - internal Status(TwainSession session) : base(session) { } + internal Status(ITwainSessionInternal session) : base(session) { } /// /// Returns the current Condition Code for the Source Manager. /// diff --git a/NTwain/Triplets/DGControl/DGControl.StatusUtf8.cs b/NTwain/Triplets/DGControl/DGControl.StatusUtf8.cs index 9badf4f..b857109 100644 --- a/NTwain/Triplets/DGControl/DGControl.StatusUtf8.cs +++ b/NTwain/Triplets/DGControl/DGControl.StatusUtf8.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class StatusUtf8 : OpBase { - internal StatusUtf8(TwainSession session) : base(session) { } + internal StatusUtf8(ITwainSessionInternal session) : base(session) { } /// /// Translate the contents of a TW_STATUS structure received from a Source into a localized UTF-8 /// encoded string. diff --git a/NTwain/Triplets/DGControl/DGControl.UserInterface.cs b/NTwain/Triplets/DGControl/DGControl.UserInterface.cs index 1c2faa1..10e4d25 100644 --- a/NTwain/Triplets/DGControl/DGControl.UserInterface.cs +++ b/NTwain/Triplets/DGControl/DGControl.UserInterface.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class UserInterface : OpBase { - internal UserInterface(TwainSession session) : base(session) { } + internal UserInterface(ITwainSessionInternal session) : base(session) { } /// /// This operation causes the Source’s user interface, if displayed during the /// EnableDS operation, to be lowered. The Source is returned to @@ -23,7 +23,7 @@ namespace NTwain.Triplets var rc = PInvoke.DsmEntry(Session.AppId, Session.SourceId, Message.DisableDS, userInterface); if (rc == ReturnCode.Success) { - Session.State = 4; + Session.ChangeState(4, true); } return rc; } diff --git a/NTwain/Triplets/DGControl/DGControl.XferGroup.cs b/NTwain/Triplets/DGControl/DGControl.XferGroup.cs index 7a93820..f9c37b3 100644 --- a/NTwain/Triplets/DGControl/DGControl.XferGroup.cs +++ b/NTwain/Triplets/DGControl/DGControl.XferGroup.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class XferGroup : OpBase { - internal XferGroup(TwainSession session) : base(session) { } + internal XferGroup(ITwainSessionInternal session) : base(session) { } /// /// Returns the Data Group (the type of data) for the upcoming transfer. The Source is required to /// only supply one of the DGs specified in the SupportedGroups field of origin. diff --git a/NTwain/Triplets/DGControl/DGControl.cs b/NTwain/Triplets/DGControl/DGControl.cs index cbc7bf2..f475586 100644 --- a/NTwain/Triplets/DGControl/DGControl.cs +++ b/NTwain/Triplets/DGControl/DGControl.cs @@ -6,8 +6,8 @@ namespace NTwain.Triplets /// public sealed class DGControl { - TwainSession _session; - internal DGControl(TwainSession session) + ITwainSessionInternal _session; + internal DGControl(ITwainSessionInternal session) { if (session == null) { throw new ArgumentNullException("session"); } _session = session; diff --git a/NTwain/Triplets/DGImage/DGImage.CieColor.cs b/NTwain/Triplets/DGImage/DGImage.CieColor.cs index 9aa8576..ada1bf5 100644 --- a/NTwain/Triplets/DGImage/DGImage.CieColor.cs +++ b/NTwain/Triplets/DGImage/DGImage.CieColor.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class CieColor : OpBase { - internal CieColor(TwainSession session) : base(session) { } + internal CieColor(ITwainSessionInternal session) : base(session) { } /// /// This operation causes the Source to report the currently active parameters to be used in diff --git a/NTwain/Triplets/DGImage/DGImage.ExtImageInfo.cs b/NTwain/Triplets/DGImage/DGImage.ExtImageInfo.cs index ef3a81a..ab8007d 100644 --- a/NTwain/Triplets/DGImage/DGImage.ExtImageInfo.cs +++ b/NTwain/Triplets/DGImage/DGImage.ExtImageInfo.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class ExtImageInfo : OpBase { - internal ExtImageInfo(TwainSession session) : base(session) { } + internal ExtImageInfo(ITwainSessionInternal session) : base(session) { } public ReturnCode Get(TWExtImageInfo info) { diff --git a/NTwain/Triplets/DGImage/DGImage.GrayResponse.cs b/NTwain/Triplets/DGImage/DGImage.GrayResponse.cs index f3be249..3315506 100644 --- a/NTwain/Triplets/DGImage/DGImage.GrayResponse.cs +++ b/NTwain/Triplets/DGImage/DGImage.GrayResponse.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class GrayResponse : OpBase { - internal GrayResponse(TwainSession session) : base(session) { } + internal GrayResponse(ITwainSessionInternal session) : base(session) { } /// /// The Reset operation causes the Source to use its "identity response curve." The identity diff --git a/NTwain/Triplets/DGImage/DGImage.IccProfile.cs b/NTwain/Triplets/DGImage/DGImage.IccProfile.cs index e37796d..50024ba 100644 --- a/NTwain/Triplets/DGImage/DGImage.IccProfile.cs +++ b/NTwain/Triplets/DGImage/DGImage.IccProfile.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class IccProfile : OpBase { - internal IccProfile(TwainSession session) : base(session) { } + internal IccProfile(ITwainSessionInternal session) : base(session) { } /// /// This operation provides the application with the ICC profile associated with the image which is diff --git a/NTwain/Triplets/DGImage/DGImage.ImageFileXfer.cs b/NTwain/Triplets/DGImage/DGImage.ImageFileXfer.cs index b954962..640b051 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageFileXfer.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageFileXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class ImageFileXfer : OpBase { - internal ImageFileXfer(TwainSession session) : base(session) { } + internal ImageFileXfer(ITwainSessionInternal session) : base(session) { } /// /// This operation is used to initiate the transfer of an image from the Source to the application via diff --git a/NTwain/Triplets/DGImage/DGImage.ImageInfo.cs b/NTwain/Triplets/DGImage/DGImage.ImageInfo.cs index 83ceecb..80747aa 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageInfo.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageInfo.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class ImageInfo : OpBase { - internal ImageInfo(TwainSession session) : base(session) { } + internal ImageInfo(ITwainSessionInternal session) : base(session) { } public ReturnCode Get(out TWImageInfo info) { diff --git a/NTwain/Triplets/DGImage/DGImage.ImageLayout.cs b/NTwain/Triplets/DGImage/DGImage.ImageLayout.cs index 332948a..5933cee 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageLayout.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageLayout.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class ImageLayout : OpBase { - internal ImageLayout(TwainSession session) : base(session) { } + internal ImageLayout(ITwainSessionInternal session) : base(session) { } public ReturnCode Get(out TWImageLayout layout) { diff --git a/NTwain/Triplets/DGImage/DGImage.ImageMemFileXfer.cs b/NTwain/Triplets/DGImage/DGImage.ImageMemFileXfer.cs index 251e16e..2788959 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageMemFileXfer.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageMemFileXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class ImageMemFileXfer : OpBase { - internal ImageMemFileXfer(TwainSession session) : base(session) { } + internal ImageMemFileXfer(ITwainSessionInternal session) : base(session) { } /// /// This operation is used to initiate the transfer of an image from the Source to the application via diff --git a/NTwain/Triplets/DGImage/DGImage.ImageMemXfer.cs b/NTwain/Triplets/DGImage/DGImage.ImageMemXfer.cs index 5379d2a..b060e24 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageMemXfer.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageMemXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class ImageMemXfer : OpBase { - internal ImageMemXfer(TwainSession session) : base(session) { } + internal ImageMemXfer(ITwainSessionInternal session) : base(session) { } /// /// This operation is used to initiate the transfer of an image from the Source to the application via diff --git a/NTwain/Triplets/DGImage/DGImage.ImageNativeXfer.cs b/NTwain/Triplets/DGImage/DGImage.ImageNativeXfer.cs index be80486..c827d9b 100644 --- a/NTwain/Triplets/DGImage/DGImage.ImageNativeXfer.cs +++ b/NTwain/Triplets/DGImage/DGImage.ImageNativeXfer.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { sealed class ImageNativeXfer : OpBase { - internal ImageNativeXfer(TwainSession session) : base(session) { } + internal ImageNativeXfer(ITwainSessionInternal session) : base(session) { } /// /// Causes the transfer of an image’s data from the Source to the application, via the Native transfer diff --git a/NTwain/Triplets/DGImage/DGImage.JpegCompression.cs b/NTwain/Triplets/DGImage/DGImage.JpegCompression.cs index 1ce6489..8c06f7f 100644 --- a/NTwain/Triplets/DGImage/DGImage.JpegCompression.cs +++ b/NTwain/Triplets/DGImage/DGImage.JpegCompression.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class JpegCompression : OpBase { - internal JpegCompression(TwainSession session) : base(session) { } + internal JpegCompression(ITwainSessionInternal session) : base(session) { } /// /// Causes the Source to return the parameters that will be used during the compression of data diff --git a/NTwain/Triplets/DGImage/DGImage.Palette8.cs b/NTwain/Triplets/DGImage/DGImage.Palette8.cs index 2e2514c..47557d0 100644 --- a/NTwain/Triplets/DGImage/DGImage.Palette8.cs +++ b/NTwain/Triplets/DGImage/DGImage.Palette8.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class Palette8 : OpBase { - internal Palette8(TwainSession session) : base(session) { } + internal Palette8(ITwainSessionInternal session) : base(session) { } /// /// This operation causes the Source to report its current palette information. diff --git a/NTwain/Triplets/DGImage/DGImage.RgbResponse.cs b/NTwain/Triplets/DGImage/DGImage.RgbResponse.cs index 1f2fba7..cc74923 100644 --- a/NTwain/Triplets/DGImage/DGImage.RgbResponse.cs +++ b/NTwain/Triplets/DGImage/DGImage.RgbResponse.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets { public sealed class RgbResponse : OpBase { - internal RgbResponse(TwainSession session) : base(session) { } + internal RgbResponse(ITwainSessionInternal session) : base(session) { } /// /// Causes the Source to use its "identity" response curves for future RGB transfers. The identity diff --git a/NTwain/Triplets/DGImage/DGImage.cs b/NTwain/Triplets/DGImage/DGImage.cs index d42ce9c..1543877 100644 --- a/NTwain/Triplets/DGImage/DGImage.cs +++ b/NTwain/Triplets/DGImage/DGImage.cs @@ -6,8 +6,8 @@ namespace NTwain.Triplets /// public sealed class DGImage { - TwainSession _session; - internal DGImage(TwainSession session) + ITwainSessionInternal _session; + internal DGImage(ITwainSessionInternal session) { if (session == null) { throw new ArgumentNullException("session"); } _session = session; diff --git a/NTwain/Triplets/OpBase.cs b/NTwain/Triplets/OpBase.cs index ad72de6..4fcbc13 100644 --- a/NTwain/Triplets/OpBase.cs +++ b/NTwain/Triplets/OpBase.cs @@ -11,16 +11,15 @@ namespace NTwain.Triplets /// public abstract class OpBase { - TwainSession _session; /// /// Initializes a new instance of the class. /// /// The session. /// - protected OpBase(TwainSession session) + internal OpBase(ITwainSessionInternal session) { if (session == null) { throw new ArgumentNullException("session"); } - _session = session; + Session = session; } /// @@ -29,6 +28,6 @@ namespace NTwain.Triplets /// /// The session. /// - protected TwainSession Session { get { return _session; } } + internal ITwainSessionInternal Session { get; private set; } } } diff --git a/NTwain/TwainSession.cs b/NTwain/TwainSession.cs index 13d85d5..8c35c8c 100644 --- a/NTwain/TwainSession.cs +++ b/NTwain/TwainSession.cs @@ -19,7 +19,7 @@ namespace NTwain /// /// Provides a session for working with TWAIN api in an application. /// - public class TwainSession : IMessageFilter, INotifyPropertyChanged + public class TwainSession : ITwainSessionInternal, IMessageFilter, INotifyPropertyChanged { /// /// Initializes a new instance of the class. @@ -62,21 +62,11 @@ namespace NTwain } } - int _state; /// /// Gets the current state number as defined by the TWAIN spec. /// /// The state. - public int State - { - get { return _state; } - internal set - { - Debug.WriteLine("TWAIN State = " + value); - _state = value; - RaisePropertyChanged("State"); - } - } + public int State { get; private set; } /// /// Gets or sets a value indicating whether callback is used parts of source communication @@ -165,32 +155,20 @@ namespace NTwain #endregion - #region quickies + #region state transition calls - - /// - /// Verifies the session is within the specified state range (inclusive). Throws - /// if violated. - /// - /// The allowed minimum. - /// The allowed maximum. - /// The triplet data group. - /// The triplet data argument type. - /// The triplet message. - /// - internal void VerifyState(int allowedMinimum, int allowedMaximum, DataGroups group, DataArgumentType dataArgumentType, NTwain.Values.Message message) + void ITwainSessionInternal.ChangeState(int newState, bool notifyChange) { - if (EnforceState && (State < allowedMinimum || State > allowedMaximum)) - { - throw new TwainStateException(State, allowedMinimum, allowedMaximum, group, dataArgumentType, message, - string.Format("TWAIN state {0} does not match required range {1}-{2} for operation {3}-{4}-{5}.", - State, allowedMinimum, allowedMaximum, group, dataArgumentType, message)); - } + Debug.WriteLine("TWAIN State = " + newState); + State = newState; + if (notifyChange) { RaisePropertyChanged("State"); } + } + ICommitable ITwainSessionInternal.GetPendingStateChanger(int newState) + { + return new TentativeStateChanger(this, newState); } - #endregion - #region state transition calls HandleRef _parentHandle; /// @@ -815,40 +793,25 @@ namespace NTwain #region nested stuff - /// - /// Gets the pending state changer and tentatively changes the session state to the specified value. - /// Value will only stick if committed. - /// - /// The state. - /// - internal ICommitable GetPendingStateChanger(int state) - { - return new TentativeStateChanger(this, state); - } - - internal interface ICommitable : IDisposable - { - void Commit(); - } class TentativeStateChanger : ICommitable { bool _commit; - TwainSession _session; + ITwainSessionInternal _session; int _origState; int _newState; - public TentativeStateChanger(TwainSession session, int newState) + public TentativeStateChanger(ITwainSessionInternal session, int newState) { _session = session; _origState = session.State; _newState = newState; - _session._state = newState; + _session.ChangeState(newState, false); } public void Commit() { if (_session.State == _newState) { - _session.State = _session.State; + _session.ChangeState(_newState, true); } _commit = true; } @@ -859,7 +822,7 @@ namespace NTwain { if (!_commit && _session.State == _newState) { - _session._state = _origState; + _session.ChangeState(_origState, false); } } diff --git a/NTwain/TwainSessionExtensions.cs b/NTwain/TwainSessionExtensions.cs index 6bd7831..b133b74 100644 --- a/NTwain/TwainSessionExtensions.cs +++ b/NTwain/TwainSessionExtensions.cs @@ -62,6 +62,28 @@ namespace NTwain return list; } + /// + /// Verifies the session is within the specified state range (inclusive). Throws + /// if violated. + /// + /// The session. + /// The allowed minimum. + /// The allowed maximum. + /// The triplet data group. + /// The triplet data argument type. + /// The triplet message. + /// + internal static void VerifyState(this ITwainSessionInternal session, int allowedMinimum, int allowedMaximum, DataGroups group, DataArgumentType dataArgumentType, NTwain.Values.Message message) + { + if (session.EnforceState && (session.State < allowedMinimum || session.State > allowedMaximum)) + { + throw new TwainStateException(session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message, + string.Format("TWAIN state {0} does not match required range {1}-{2} for operation {3}-{4}-{5}.", + session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message)); + } + } + + #region common caps /// diff --git a/Tests/NTwain.Tests/TwainSessionTests.cs b/Tests/NTwain.Tests/TwainSessionTests.cs index e36c2e5..6cd38b6 100644 --- a/Tests/NTwain.Tests/TwainSessionTests.cs +++ b/Tests/NTwain.Tests/TwainSessionTests.cs @@ -12,9 +12,9 @@ namespace NTwain.Tests [ExpectedException(typeof(TwainStateException), "State check failed to throw.")] public void VerifyState_Throws_When_State_Is_Enforced() { - TwainSession session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); + ITwainSessionInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); session.EnforceState = true; - session.State = 4; + session.ChangeState(4, false); session.VerifyState(6, 6, DataGroups.Image, DataArgumentType.ImageNativeXfer, Message.Get); } @@ -22,9 +22,9 @@ namespace NTwain.Tests [TestMethod] public void VerifyState_No_Throws_When_State_Is_Not_Enforced() { - TwainSession session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); + ITwainSessionInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); session.EnforceState = false; - session.State = 4; + session.ChangeState(4, false); session.VerifyState(6, 6, DataGroups.Image, DataArgumentType.ImageNativeXfer, Message.Get); }