From 00f9ef0f4fb1603a5b6d1c2019358f090c4dac2a Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Wed, 25 Feb 2009 20:58:42 -0600 Subject: [PATCH] sane.ds: Fully support ICAP_PIXELTYPE. --- dlls/sane.ds/capability.c | 144 +++++++++++++++++++++++++++++++++++--- dlls/sane.ds/options.c | 40 +++++++++++ dlls/sane.ds/sane_i.h | 6 +- 3 files changed, 180 insertions(+), 10 deletions(-) diff --git a/dlls/sane.ds/capability.c b/dlls/sane.ds/capability.c index f8a300c4bb..0604734374 100644 --- a/dlls/sane.ds/capability.c +++ b/dlls/sane.ds/capability.c @@ -265,15 +265,105 @@ static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action return twCC; } +#ifdef SONAME_LIBSANE +static BOOL pixeltype_to_sane_mode(TW_UINT16 pixeltype, SANE_String mode, int len) +{ + SANE_String_Const m = NULL; + switch (pixeltype) + { + case TWPT_GRAY: + m = SANE_VALUE_SCAN_MODE_GRAY; + break; + case TWPT_RGB: + m = SANE_VALUE_SCAN_MODE_COLOR; + break; + case TWPT_BW: + m = SANE_VALUE_SCAN_MODE_LINEART; + break; + } + if (! m) + return FALSE; + if (strlen(m) >= len) + return FALSE; + strcpy(mode, m); + return TRUE; +} +static BOOL sane_mode_to_pixeltype(SANE_String_Const mode, TW_UINT16 *pixeltype) +{ + if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) + *pixeltype = TWPT_BW; + else if (memcmp(mode, SANE_VALUE_SCAN_MODE_GRAY, strlen(SANE_VALUE_SCAN_MODE_GRAY)) == 0) + *pixeltype = TWPT_GRAY; + else if (strcmp(mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) + *pixeltype = TWPT_RGB; + else + return FALSE; + + return TRUE; +} + +static TW_UINT16 sane_status_to_twcc(SANE_Status rc) +{ + switch (rc) + { + case SANE_STATUS_GOOD: + return TWCC_SUCCESS; + case SANE_STATUS_UNSUPPORTED: + return TWCC_CAPUNSUPPORTED; + case SANE_STATUS_JAMMED: + return TWCC_PAPERJAM; + case SANE_STATUS_NO_MEM: + return TWCC_LOWMEMORY; + case SANE_STATUS_ACCESS_DENIED: + return TWCC_DENIED; + + case SANE_STATUS_IO_ERROR: + case SANE_STATUS_NO_DOCS: + case SANE_STATUS_COVER_OPEN: + case SANE_STATUS_EOF: + case SANE_STATUS_INVAL: + case SANE_STATUS_CANCELLED: + case SANE_STATUS_DEVICE_BUSY: + default: + return TWCC_BUMMER; + } +} +#endif + /* ICAP_PIXELTYPE */ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action) { - static const TW_UINT32 possible_values[] = { TWPT_BW, TWPT_GRAY, TWPT_RGB }; - TW_UINT32 val; TW_UINT16 twCC = TWCC_BADCAP; +#ifdef SONAME_LIBSANE + TW_UINT32 possible_values[3]; + int possible_value_count; + TW_UINT32 val; + SANE_Status rc; + SANE_Int status; + SANE_String_Const *choices; + char current_mode[64]; + TW_UINT16 current_pixeltype = TWPT_BW; + SANE_Char mode[64]; TRACE("ICAP_PIXELTYPE\n"); + rc = sane_option_probe_mode(activeDS.deviceHandle, &choices, current_mode, sizeof(current_mode)); + if (rc != SANE_STATUS_GOOD) + { + ERR("Unable to retrieve mode from sane, ICAP_PIXELTYPE unsupported\n"); + return twCC; + } + + sane_mode_to_pixeltype(current_mode, ¤t_pixeltype); + + /* Sane does not support a concept of a default mode, so we simply cache + * the first mode we find */ + if (! activeDS.PixelTypeSet) + { + activeDS.PixelTypeSet = TRUE; + activeDS.defaultPixelType = current_pixeltype; + } + switch (action) { case MSG_QUERYSUPPORT: @@ -282,32 +372,68 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio break; case MSG_GET: - twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]), - TWTY_UINT16, activeDS.capXferMech, TWPT_BW); + for (possible_value_count = 0; choices && *choices && possible_value_count < 3; choices++) + { + TW_UINT16 pix; + if (sane_mode_to_pixeltype(*choices, &pix)) + possible_values[possible_value_count++] = pix; + } + twCC = msg_get_enum(pCapability, possible_values, possible_value_count, + TWTY_UINT16, current_pixeltype, activeDS.defaultPixelType); break; case MSG_SET: twCC = msg_set(pCapability, &val); if (twCC == TWCC_SUCCESS) { - activeDS.capPixelType = (TW_UINT16) val; - FIXME("Partial Stub: PIXELTYPE set to %d, but ignored\n", val); + if (! pixeltype_to_sane_mode(val, mode, sizeof(mode))) + return TWCC_BADVALUE; + + status = 0; + rc = sane_option_set_str(activeDS.deviceHandle, "mode", mode, &status); + /* Some SANE devices use 'Grayscale' instead of the standard 'Gray' */ + if (rc == SANE_STATUS_INVAL && strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) + { + strcpy(mode, "Grayscale"); + rc = sane_option_set_str(activeDS.deviceHandle, "mode", mode, &status); + } + if (rc != SANE_STATUS_GOOD) + return sane_status_to_twcc(rc); + if (status & SANE_INFO_RELOAD_PARAMS) + psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param); } break; case MSG_GETDEFAULT: - twCC = set_onevalue(pCapability, TWTY_UINT16, TWPT_BW); + twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.defaultPixelType); break; case MSG_RESET: - activeDS.capPixelType = TWPT_BW; + current_pixeltype = activeDS.defaultPixelType; + if (! pixeltype_to_sane_mode(current_pixeltype, mode, sizeof(mode))) + return TWCC_BADVALUE; + + status = 0; + rc = sane_option_set_str(activeDS.deviceHandle, "mode", mode, &status); + /* Some SANE devices use 'Grayscale' instead of the standard 'Gray' */ + if (rc == SANE_STATUS_INVAL && strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) + { + strcpy(mode, "Grayscale"); + rc = sane_option_set_str(activeDS.deviceHandle, "mode", mode, &status); + } + if (rc != SANE_STATUS_GOOD) + return sane_status_to_twcc(rc); + if (status & SANE_INFO_RELOAD_PARAMS) + psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param); + /* .. fall through intentional .. */ case MSG_GETCURRENT: - twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.capPixelType); + twCC = set_onevalue(pCapability, TWTY_UINT16, current_pixeltype); break; } +#endif return twCC; } diff --git a/dlls/sane.ds/options.c b/dlls/sane.ds/options.c index 99247465c4..98d83dcf48 100644 --- a/dlls/sane.ds/options.c +++ b/dlls/sane.ds/options.c @@ -34,6 +34,13 @@ static SANE_Status sane_find_option(SANE_Handle h, const char *option_name, const SANE_Option_Descriptor *opt; int i; + /* Debian, in 32_net_backend_standard_fix.dpatch, + * forces a frontend (that's us) to reload options + * manually by invoking get_option_descriptor. */ + opt = psane_get_option_descriptor(h, 0); + if (! opt) + return SANE_STATUS_EOF; + rc = psane_control_option(h, 0, SANE_ACTION_GET_VALUE, &optcount, NULL); if (rc != SANE_STATUS_GOOD) return rc; @@ -78,6 +85,20 @@ SANE_Status sane_option_set_int(SANE_Handle h, const char *option_name, SANE_Int return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); } +/* Important: SANE has the side effect of of overwriting val with the returned value */ +SANE_Status sane_option_set_str(SANE_Handle h, const char *option_name, SANE_String val, SANE_Int *status) +{ + SANE_Status rc; + int optno; + const SANE_Option_Descriptor *opt; + + rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_STRING); + if (rc != SANE_STATUS_GOOD) + return rc; + + return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) val, status); +} + SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, SANE_Int *minval, SANE_Int *maxval, SANE_Int *quant) { SANE_Status rc; @@ -97,4 +118,23 @@ SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, return rc; } + +SANE_Status sane_option_probe_mode(SANE_Handle h, SANE_String_Const **choices, char *current, int current_size) +{ + SANE_Status rc; + int optno; + const SANE_Option_Descriptor *opt; + rc = sane_find_option(h, "mode", &opt, &optno, SANE_TYPE_STRING); + if (rc != SANE_STATUS_GOOD) + return rc; + + if (choices && opt->constraint_type == SANE_CONSTRAINT_STRING_LIST) + *choices = (SANE_String_Const *) opt->constraint.string_list; + + if (opt->size < current_size) + return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, current, NULL); + else + return SANE_STATUS_NO_MEM; + +} #endif diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 79e2cce00d..9d0d123382 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -25,6 +25,7 @@ #ifdef SONAME_LIBSANE # include +# include #define MAKE_FUNCPTR(f) typeof(f) * p##f; MAKE_FUNCPTR(sane_init) @@ -74,7 +75,8 @@ struct tagActiveDS #endif /* Capabilities */ TW_UINT16 capXferMech; /* ICAP_XFERMECH */ - TW_UINT16 capPixelType; /* ICAP_PIXELTYPE */ + BOOL PixelTypeSet; + TW_UINT16 defaultPixelType; /* ICAP_PIXELTYPE */ BOOL XResolutionSet; TW_FIX32 defaultXResolution; BOOL YResolutionSet; @@ -221,7 +223,9 @@ HWND ScanningDialogBox(HWND dialog, LONG progress); #ifdef SONAME_LIBSANE SANE_Status sane_option_get_int(SANE_Handle h, const char *option_name, SANE_Int *val); SANE_Status sane_option_set_int(SANE_Handle h, const char *option_name, SANE_Int val, SANE_Int *status); +SANE_Status sane_option_set_str(SANE_Handle h, const char *option_name, SANE_String val, SANE_Int *status); SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, SANE_Int *minval, SANE_Int *maxval, SANE_Int *quant); +SANE_Status sane_option_probe_mode(SANE_Handle h, SANE_String_Const **choices, char *current, int current_size); #endif -- 2.32.0.93.g670b81a890