mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-21 04:37:47 +03:00
Finish implementing TwainScan worker method
This commit is contained in:
parent
a7ccd947df
commit
b6fd79c4e3
@ -110,7 +110,6 @@ message TwainScanResponse {
|
||||
TwainPageStart pageStart = 2;
|
||||
TwainNativeImage nativeImage = 3;
|
||||
TwainMemoryBuffer memoryBuffer = 4;
|
||||
TwainScanComplete scanComplete = 5;
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,6 +140,3 @@ message TwainMemoryBuffer {
|
||||
int32 yOffset = 5;
|
||||
int32 bytesPerRow = 6;
|
||||
}
|
||||
|
||||
message TwainScanComplete {
|
||||
}
|
||||
|
@ -53,24 +53,34 @@ public class WorkerServiceAdapter
|
||||
{
|
||||
OptionsXml = options.ToXml()
|
||||
};
|
||||
var streamingCall = _client.Scan(req, cancellationToken: cancelToken);
|
||||
while (await streamingCall.ResponseStream.MoveNext())
|
||||
try
|
||||
{
|
||||
var resp = streamingCall.ResponseStream.Current;
|
||||
RemotingHelper.HandleErrors(resp.Error);
|
||||
if (resp.PageStart != null)
|
||||
var streamingCall = _client.Scan(req, cancellationToken: cancelToken);
|
||||
while (await streamingCall.ResponseStream.MoveNext())
|
||||
{
|
||||
scanEvents.PageStart();
|
||||
var resp = streamingCall.ResponseStream.Current;
|
||||
RemotingHelper.HandleErrors(resp.Error);
|
||||
if (resp.PageStart != null)
|
||||
{
|
||||
scanEvents.PageStart();
|
||||
}
|
||||
if (resp.Progress != null)
|
||||
{
|
||||
scanEvents.PageProgress(resp.Progress.Value);
|
||||
}
|
||||
if (resp.Image != null)
|
||||
{
|
||||
var renderableImage = SerializedImageHelper.Deserialize(scanningContext, resp.Image,
|
||||
new SerializedImageHelper.DeserializeOptions());
|
||||
imageCallback?.Invoke(renderableImage, resp.Image.RenderedFilePath);
|
||||
}
|
||||
}
|
||||
if (resp.Progress != null)
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
if (ex.Status.StatusCode != StatusCode.Cancelled)
|
||||
{
|
||||
scanEvents.PageProgress(resp.Progress.Value);
|
||||
}
|
||||
if (resp.Image != null)
|
||||
{
|
||||
var renderableImage = SerializedImageHelper.Deserialize(scanningContext, resp.Image,
|
||||
new SerializedImageHelper.DeserializeOptions());
|
||||
imageCallback?.Invoke(renderableImage, resp.Image.RenderedFilePath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,22 +131,32 @@ public class WorkerServiceAdapter
|
||||
{
|
||||
OptionsXml = options.ToXml()
|
||||
};
|
||||
var streamingCall = _client.TwainScan(req, cancellationToken: cancelToken);
|
||||
while (await streamingCall.ResponseStream.MoveNext())
|
||||
try
|
||||
{
|
||||
var resp = streamingCall.ResponseStream.Current;
|
||||
RemotingHelper.HandleErrors(resp.Error);
|
||||
if (resp.PageStart != null)
|
||||
var streamingCall = _client.TwainScan(req, cancellationToken: cancelToken);
|
||||
while (await streamingCall.ResponseStream.MoveNext())
|
||||
{
|
||||
twainEvents.PageStart(resp.PageStart);
|
||||
var resp = streamingCall.ResponseStream.Current;
|
||||
RemotingHelper.HandleErrors(resp.Error);
|
||||
if (resp.PageStart != null)
|
||||
{
|
||||
twainEvents.PageStart(resp.PageStart);
|
||||
}
|
||||
if (resp.NativeImage != null)
|
||||
{
|
||||
twainEvents.NativeImageTransferred(resp.NativeImage);
|
||||
}
|
||||
if (resp.MemoryBuffer != null)
|
||||
{
|
||||
twainEvents.MemoryBufferTransferred(resp.MemoryBuffer);
|
||||
}
|
||||
}
|
||||
if (resp.NativeImage != null)
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
if (ex.Status.StatusCode != StatusCode.Cancelled)
|
||||
{
|
||||
twainEvents.NativeImageTransferred(resp.NativeImage);
|
||||
}
|
||||
if (resp.MemoryBuffer != null)
|
||||
{
|
||||
twainEvents.MemoryBufferTransferred(resp.MemoryBuffer);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using NAPS2.ImportExport.Email.Mapi;
|
||||
using NAPS2.ImportExport.Pdf;
|
||||
using NAPS2.Scan;
|
||||
using NAPS2.Scan.Internal;
|
||||
using NAPS2.Scan.Internal.Twain;
|
||||
using NAPS2.Scan.Wia;
|
||||
using NAPS2.Wia;
|
||||
using NAPS2.Serialization;
|
||||
@ -22,13 +23,15 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
private readonly AutoResetEvent _ongoingCallFinished = new(false);
|
||||
private int _ongoingCallCount;
|
||||
|
||||
public WorkerServiceImpl(ScanningContext scanningContext, ThumbnailRenderer thumbnailRenderer, IMapiWrapper mapiWrapper)
|
||||
public WorkerServiceImpl(ScanningContext scanningContext, ThumbnailRenderer thumbnailRenderer,
|
||||
IMapiWrapper mapiWrapper)
|
||||
: this(scanningContext, new RemoteScanController(scanningContext),
|
||||
thumbnailRenderer, mapiWrapper)
|
||||
{
|
||||
}
|
||||
|
||||
internal WorkerServiceImpl(ScanningContext scanningContext, IRemoteScanController remoteScanController, ThumbnailRenderer thumbnailRenderer,
|
||||
internal WorkerServiceImpl(ScanningContext scanningContext, IRemoteScanController remoteScanController,
|
||||
ThumbnailRenderer thumbnailRenderer,
|
||||
IMapiWrapper mapiWrapper)
|
||||
{
|
||||
_scanningContext = scanningContext;
|
||||
@ -89,7 +92,8 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<GetDeviceListResponse> GetDeviceList(GetDeviceListRequest request, ServerCallContext context)
|
||||
public override async Task<GetDeviceListResponse> GetDeviceList(GetDeviceListRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
using var callRef = StartCall();
|
||||
try
|
||||
@ -107,10 +111,10 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task Scan(ScanRequest request, IServerStreamWriter<ScanResponse> responseStream, ServerCallContext context)
|
||||
public override async Task Scan(ScanRequest request, IServerStreamWriter<ScanResponse> responseStream,
|
||||
ServerCallContext context)
|
||||
{
|
||||
using var callRef = StartCall();
|
||||
Log.Error("Scan start");
|
||||
var sequencedWriter = new SequencedWriter<ScanResponse>(responseStream);
|
||||
try
|
||||
{
|
||||
@ -148,7 +152,8 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
await sequencedWriter.WaitForCompletion();
|
||||
}
|
||||
|
||||
public override async Task<SendMapiEmailResponse> SendMapiEmail(SendMapiEmailRequest request, ServerCallContext context)
|
||||
public override async Task<SendMapiEmailResponse> SendMapiEmail(SendMapiEmailRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
using var callRef = StartCall();
|
||||
try
|
||||
@ -166,7 +171,8 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<RenderThumbnailResponse> RenderThumbnail(RenderThumbnailRequest request, ServerCallContext context)
|
||||
public override async Task<RenderThumbnailResponse> RenderThumbnail(RenderThumbnailRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
using var callRef = StartCall();
|
||||
try
|
||||
@ -229,6 +235,38 @@ public class WorkerServiceImpl : WorkerService.WorkerServiceBase
|
||||
return Task.FromResult(new StopWorkerResponse());
|
||||
}
|
||||
|
||||
public override async Task TwainScan(TwainScanRequest request,
|
||||
IServerStreamWriter<TwainScanResponse> responseStream, ServerCallContext context)
|
||||
{
|
||||
using var callRef = StartCall();
|
||||
var sequencedWriter = new SequencedWriter<TwainScanResponse>(responseStream);
|
||||
try
|
||||
{
|
||||
var twainEvents = new TwainEvents(
|
||||
pageStart => sequencedWriter.Write(new TwainScanResponse
|
||||
{
|
||||
PageStart = pageStart
|
||||
}),
|
||||
nativeImage => sequencedWriter.Write(new TwainScanResponse
|
||||
{
|
||||
NativeImage = nativeImage
|
||||
}),
|
||||
memoryBuffer => sequencedWriter.Write(new TwainScanResponse
|
||||
{
|
||||
MemoryBuffer = memoryBuffer
|
||||
})
|
||||
);
|
||||
var twainController = new LocalTwainController();
|
||||
var options = request.OptionsXml.FromXml<ScanOptions>();
|
||||
await twainController.StartScan(options, twainEvents, context.CancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sequencedWriter.Write(new TwainScanResponse { Error = RemotingHelper.ToError(e) });
|
||||
}
|
||||
await sequencedWriter.WaitForCompletion();
|
||||
}
|
||||
|
||||
public event EventHandler? OnStop;
|
||||
|
||||
private CallReference StartCall() => new(this);
|
||||
|
@ -3,7 +3,7 @@
|
||||
internal class ScanBridgeFactory : IScanBridgeFactory
|
||||
{
|
||||
private readonly InProcScanBridge _inProcScanBridge;
|
||||
private readonly WorkerScanBridge _workerScanBridge;
|
||||
private readonly WorkerScanBridge _workerScanBridge; // TODO: remove
|
||||
private readonly NetworkScanBridge _networkScanBridge;
|
||||
|
||||
public ScanBridgeFactory(ScanningContext scanningContext)
|
||||
@ -27,11 +27,6 @@ internal class ScanBridgeFactory : IScanBridgeFactory
|
||||
// The physical scanner is connected to a different computer, so we connect to a NAPS2 server process over the network
|
||||
return _networkScanBridge;
|
||||
}
|
||||
if (options.Driver == Driver.Twain && options.TwainOptions.Dsm != TwainDsm.NewX64 && Environment.Is64BitProcess)
|
||||
{
|
||||
// 32-bit twain can only be used by a 32-bit process, so we use a separate worker process
|
||||
return _workerScanBridge;
|
||||
}
|
||||
return _inProcScanBridge;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ namespace NAPS2.Scan.Internal.Twain;
|
||||
public interface ITwainEvents
|
||||
{
|
||||
void PageStart(TwainPageStart pageStart);
|
||||
|
||||
|
||||
void NativeImageTransferred(TwainNativeImage nativeImage);
|
||||
|
||||
|
||||
void MemoryBufferTransferred(TwainMemoryBuffer memoryBuffer);
|
||||
}
|
33
NAPS2.Sdk/Scan/Internal/Twain/TwainEvents.cs
Normal file
33
NAPS2.Sdk/Scan/Internal/Twain/TwainEvents.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using NAPS2.Remoting.Worker;
|
||||
|
||||
namespace NAPS2.Scan.Internal.Twain;
|
||||
|
||||
class TwainEvents : ITwainEvents
|
||||
{
|
||||
private readonly Action<TwainPageStart> _pageStartCallback;
|
||||
private readonly Action<TwainNativeImage> _nativeImageCallback;
|
||||
private readonly Action<TwainMemoryBuffer> _memoryBufferCallback;
|
||||
|
||||
public TwainEvents(Action<TwainPageStart> pageStartCallback, Action<TwainNativeImage> nativeImageCallback,
|
||||
Action<TwainMemoryBuffer> memoryBufferCallback)
|
||||
{
|
||||
_pageStartCallback = pageStartCallback;
|
||||
_nativeImageCallback = nativeImageCallback;
|
||||
_memoryBufferCallback = memoryBufferCallback;
|
||||
}
|
||||
|
||||
public void PageStart(TwainPageStart pageStart)
|
||||
{
|
||||
_pageStartCallback(pageStart);
|
||||
}
|
||||
|
||||
public void NativeImageTransferred(TwainNativeImage nativeImage)
|
||||
{
|
||||
_nativeImageCallback(nativeImage);
|
||||
}
|
||||
|
||||
public void MemoryBufferTransferred(TwainMemoryBuffer memoryBuffer)
|
||||
{
|
||||
_memoryBufferCallback(memoryBuffer);
|
||||
}
|
||||
}
|
@ -24,17 +24,7 @@ internal class WorkerScanBridge : IScanBridge
|
||||
public async Task Scan(ScanOptions options, CancellationToken cancelToken, IScanEvents scanEvents, Action<ProcessedImage, PostProcessingContext> callback)
|
||||
{
|
||||
using var ctx = _scanningContext.WorkerFactory.Create();
|
||||
try
|
||||
{
|
||||
await ctx.Service.Scan(_scanningContext, options, cancelToken, scanEvents,
|
||||
(image, tempPath) => { callback(image, new PostProcessingContext { TempPath = tempPath }); });
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
if (ex.Status.StatusCode != StatusCode.Cancelled)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
await ctx.Service.Scan(_scanningContext, options, cancelToken, scanEvents,
|
||||
(image, tempPath) => { callback(image, new PostProcessingContext { TempPath = tempPath }); });
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user