From: Bernd Herd codeberg@herdsoft.com
Replace all direct calls to start_device and cancel_device by calls to SANE_Start and SANE_Cancel, controlled by the activeDS.currentState.activeDS.currentState
Allow calling sane_start more than once per sane_cancel. --- dlls/sane.ds/ds_ctrl.c | 53 ++++++++++++- dlls/sane.ds/ds_image.c | 165 +++++++++++++++++++++++---------------- dlls/sane.ds/sane_i.h | 5 ++ dlls/sane.ds/sane_main.c | 2 + dlls/sane.ds/ui.c | 1 + dlls/sane.ds/unixlib.c | 1 - 6 files changed, 157 insertions(+), 70 deletions(-)
diff --git a/dlls/sane.ds/ds_ctrl.c b/dlls/sane.ds/ds_ctrl.c index 79c268a36ae..9564ffe80d6 100644 --- a/dlls/sane.ds/ds_ctrl.c +++ b/dlls/sane.ds/ds_ctrl.c @@ -190,6 +190,29 @@ TW_UINT16 SANE_ProcessEvent (pTW_IDENTITY pOrigin, return twRC; }
+/** @brief Check if Automatic Document Feeder is enabled + * + * If the application does not set the number of images it expects, + * finish after the first image if ADF is not enabled. + * + * The source names used depends on the sane backend. + * A complete list of all values for "source" that indicates + * the use of an ADF is in SANE_CAPFeederEnabled + * + * @return TRUE if Automatic Document feeder is enabled. + */ +static +BOOL +SANE_ADF_Enabled(void) +{ + char current_source[256]; + return + sane_option_get_str("source", current_source, sizeof(current_source)) == TWCC_SUCCESS && + (current_source[0]=='A' || current_source[0]=='a'); +} + + + /* DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER */ TW_UINT16 SANE_PendingXfersEndXfer (pTW_IDENTITY pOrigin, TW_MEMREF pData) @@ -199,6 +222,9 @@ TW_UINT16 SANE_PendingXfersEndXfer (pTW_IDENTITY pOrigin,
TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
+ if (activeDS.remainingImages > 0) + activeDS.remainingImages--; + if (activeDS.currentState != 6 && activeDS.currentState != 7) { twRC = TWRC_FAILURE; @@ -206,15 +232,35 @@ TW_UINT16 SANE_PendingXfersEndXfer (pTW_IDENTITY pOrigin, } else { - pPendingXfers->Count = -1; - activeDS.currentState = 6; - if (SANE_CALL( start_device, NULL )) + pPendingXfers->Count = activeDS.remainingImages; + if (!activeDS.remainingImages || + !SANE_ADF_Enabled()) { + /* All requested images transfered. Stop scanning */ pPendingXfers->Count = 0; activeDS.currentState = 5; + SANE_Cancel(); /* Notify the application that it can close the data source */ SANE_Notify(MSG_CLOSEDSREQ); } + else + { + /* To find out if there are more Xfers waiting for us, + * we need to call sane_start. + * On success, this will prepare the next frame and + * bring us back into currentState==7 + */ + activeDS.currentState = 6; + if (SANE_Start()) + { + /* No more frames... tell the application */ + pPendingXfers->Count = 0; + activeDS.currentState = 5; + SANE_Cancel(); + /* Notify the application that it can close the data source */ + SANE_Notify(MSG_CLOSEDSREQ); + } + } twRC = TWRC_SUCCESS; activeDS.twCC = TWCC_SUCCESS; } @@ -371,6 +417,7 @@ TW_UINT16 SANE_EnableDSUserInterface (pTW_IDENTITY pOrigin, { /* no UI will be displayed, so source is ready to transfer data */ activeDS.currentState = 6; /* Transitions to state 6 directly */ + activeDS.remainingImages = activeDS.capXferCount; SANE_Notify(MSG_XFERREADY); }
diff --git a/dlls/sane.ds/ds_image.c b/dlls/sane.ds/ds_image.c index 032cc755bb4..a5e68f1ba44 100644 --- a/dlls/sane.ds/ds_image.c +++ b/dlls/sane.ds/ds_image.c @@ -26,6 +26,75 @@
WINE_DEFAULT_DEBUG_CHANNEL(twain);
+ +/* transition from state 6 to state 7. + * + * Called by either SANE_ImageMemXferGet, SANE_ImageInfoGet or + * SANE_ImageNativeXferGet, whatever the application calls first. + * + * - start the scan with a call to sane start_devince + * - open the progress dialog window + * - call get_sane_params to retrieve parameters of current scan frame + * + * @return TWAIN result code, TWRC_SUCCESS on success + */ +TW_UINT16 SANE_Start(void) +{ + TW_UINT16 twRC = TWRC_SUCCESS; + TRACE("SANE_Start currentState:%d\n", activeDS.currentState); + if (activeDS.currentState != 6) + { + twRC = TWRC_FAILURE; + activeDS.twCC = TWCC_SEQERROR; + } + else + { + /* Open progress dialog */ + activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd,0); + + /* Start the scan process in sane */ + if (SANE_CALL( start_device, NULL )) + { + activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1); + activeDS.twCC = TWCC_OPERATIONERROR; + return TWRC_FAILURE; + } + + if (get_sane_params( &activeDS.frame_params )) + { + WARN("sane_get_parameters failed\n"); + SANE_CALL( cancel_device, NULL ); + activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1); + activeDS.twCC = TWCC_OPERATIONERROR; + return TWRC_FAILURE; + } + + TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n" + , activeDS.frame_params.pixels_per_line, activeDS.frame_params.lines, + activeDS.frame_params.depth, activeDS.frame_params.format, + activeDS.frame_params.last_frame); + + activeDS.currentState = 7; + } + return twRC; +} + +/** transition from state 7 or 6 to state 5. + * + * Called when an error occurs or when the last frame + * has been transfered successfully. + * - call sane cancel_device to finish any open transfer + * - close the progress dialog box. + */ +void SANE_Cancel(void) +{ + SANE_CALL( cancel_device, NULL ); + activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1); + activeDS.currentState = 5; +} + + + /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */ TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) @@ -45,14 +114,11 @@ TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin, { if (activeDS.currentState == 6) { - /* return general image description information about the image about to be transferred */ - TRACE("Getting parameters\n"); - if (SANE_CALL( get_params, &activeDS.frame_params )) + /* Transition from state 6 to state 7 by starting the scan */ + twRC = SANE_Start(); + if (twRC != TWRC_SUCCESS) { - WARN("sane_get_parameters failed\n"); - SANE_CALL( cancel_device, NULL ); - activeDS.twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; + return twRC; } }
@@ -201,38 +267,18 @@ TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, /* Transfer an image from the source to the application */ if (activeDS.currentState == 6) { - - /* trigger scanning dialog */ - activeDS.progressWnd = ScanningDialogBox(NULL,0); - - ScanningDialogBox(activeDS.progressWnd,0); - - if (SANE_CALL( start_device, NULL )) - { - activeDS.twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; - } - - if (get_sane_params( &activeDS.frame_params )) + /* Transition from state 6 to state 7 by starting the scan */ + twRC = SANE_Start(); + if (twRC != TWRC_SUCCESS) { - WARN("sane_get_parameters failed\n"); - SANE_CALL( cancel_device, NULL ); - activeDS.twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; + return twRC; } - - TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n" - , activeDS.frame_params.pixels_per_line, activeDS.frame_params.lines, - activeDS.frame_params.depth, activeDS.frame_params.format, - activeDS.frame_params.last_frame); - - activeDS.currentState = 7; }
/* access memory buffer */ if (pImageMemXfer->Memory.Length < activeDS.frame_params.bytes_per_line) { - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_BADVALUE; return TWRC_FAILURE; } @@ -265,18 +311,15 @@ TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin,
if (retlen < activeDS.frame_params.bytes_per_line * rows) { - ScanningDialogBox(activeDS.progressWnd, -1); TRACE("sane_read: %u / %u\n", retlen, activeDS.frame_params.bytes_per_line * rows); - SANE_CALL( cancel_device, NULL ); twRC = TWRC_XFERDONE; } activeDS.twCC = TWRC_SUCCESS; } else { - ScanningDialogBox(activeDS.progressWnd, -1); WARN("sane_read: %u\n", twRC); - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_OPERATIONERROR; twRC = TWRC_FAILURE; } @@ -307,28 +350,23 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin,
TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
- if (activeDS.currentState != 6) + if (activeDS.currentState == 6) + { + /* Transition from state 6 to state 7 by starting the scan */ + twRC = SANE_Start(); + if (twRC != TWRC_SUCCESS) + { + return twRC; + } + } + + if (activeDS.currentState != 7) { twRC = TWRC_FAILURE; activeDS.twCC = TWCC_SEQERROR; } else { - /* Transfer an image from the source to the application */ - if (SANE_CALL( start_device, NULL )) - { - activeDS.twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; - } - - if (SANE_CALL( get_params, &activeDS.frame_params )) - { - WARN("sane_get_parameters failed\n"); - SANE_CALL( cancel_device, NULL ); - activeDS.twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; - } - switch (activeDS.frame_params.format) { case FMT_GRAY: @@ -337,8 +375,9 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, else { FIXME("For NATIVE, we support only 1 bit monochrome and 8 bit Grayscale, not %d\n", activeDS.frame_params.depth); - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_OPERATIONERROR; + activeDS.currentState = 6; return TWRC_FAILURE; } break; @@ -346,16 +385,12 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, break; case FMT_OTHER: FIXME("For NATIVE, we support only GRAY and RGB\n"); - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_OPERATIONERROR; + activeDS.currentState = 6; return TWRC_FAILURE; }
- TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d bpl=%d) from sane...\n" - , activeDS.frame_params.pixels_per_line, activeDS.frame_params.lines, - activeDS.frame_params.depth, activeDS.frame_params.format, - activeDS.frame_params.last_frame, activeDS.frame_params.bytes_per_line); - dib_bytes_per_line = ((activeDS.frame_params.bytes_per_line + 3) / 4) * 4; dib_bytes = activeDS.frame_params.lines * dib_bytes_per_line;
@@ -365,8 +400,9 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin,
if (!header) { - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_LOWMEMORY; + activeDS.currentState = 6; if (hDIB) GlobalFree(hDIB); return TWRC_FAILURE; @@ -441,24 +477,21 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, } line -= dib_bytes_per_line; } - activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1); - - GlobalUnlock(hDIB);
if (twRC != TWCC_SUCCESS) { WARN("sane_read: %u, reading line %d\n", twRC, i); - SANE_CALL( cancel_device, NULL ); + SANE_Cancel(); activeDS.twCC = TWCC_OPERATIONERROR; GlobalFree(hDIB); return TWRC_FAILURE; }
- SANE_CALL( cancel_device, NULL ); + GlobalUnlock(hDIB); + *pHandle = (TW_HANDLE)hDIB; twRC = TWRC_XFERDONE; activeDS.twCC = TWCC_SUCCESS; - activeDS.currentState = 7; } return twRC; } diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 9d6f28d1e80..75cc9076a9a 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -52,6 +52,9 @@ struct tagActiveDS TW_FIX32 defaultXResolution; BOOL YResolutionSet; TW_FIX32 defaultYResolution; + + /* Remaining number of images to transfer or -1 for unlimited */ + TW_INT16 remainingImages; };
extern struct tagActiveDS activeDS; @@ -60,6 +63,8 @@ extern struct tagActiveDS activeDS; extern TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action); extern TW_UINT16 SANE_SaneSetDefaults (void); extern void SANE_Notify (TW_UINT16 message); +extern TW_UINT16 SANE_Start(void); +extern void SANE_Cancel(void);
/* Implementation of operation triplets * From Application to Source (Control Information) */ diff --git a/dlls/sane.ds/sane_main.c b/dlls/sane.ds/sane_main.c index 360509e2bf6..5fd33ae2aaa 100644 --- a/dlls/sane.ds/sane_main.c +++ b/dlls/sane.ds/sane_main.c @@ -80,6 +80,8 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) activeDS.currentState = 4; activeDS.identity.Id = self->Id; activeDS.appIdentity = *pOrigin; + activeDS.capXferMech = TWSX_NATIVE; + activeDS.capXferCount = -1; return TWRC_SUCCESS; } SANE_CALL( close_ds, NULL ); diff --git a/dlls/sane.ds/ui.c b/dlls/sane.ds/ui.c index 0e32e274d9c..86a968b1907 100644 --- a/dlls/sane.ds/ui.c +++ b/dlls/sane.ds/ui.c @@ -1101,6 +1101,7 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM if (psn->lParam) { activeDS.currentState = 6; + activeDS.remainingImages = activeDS.capXferCount; SANE_Notify(MSG_XFERREADY); } break; diff --git a/dlls/sane.ds/unixlib.c b/dlls/sane.ds/unixlib.c index 0002e64eacb..9531c758746 100644 --- a/dlls/sane.ds/unixlib.c +++ b/dlls/sane.ds/unixlib.c @@ -295,7 +295,6 @@ static NTSTATUS start_device( void *args ) { SANE_Status status;
- if (device_started) return STATUS_SUCCESS; status = sane_start( device_handle ); if (status != SANE_STATUS_GOOD) {