Commit 00f9ef0f authored by Jeremy White's avatar Jeremy White Committed by Alexandre Julliard

sane.ds: Fully support ICAP_PIXELTYPE.

parent f75b5ebb
...@@ -265,15 +265,105 @@ static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action ...@@ -265,15 +265,105 @@ static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action
return twCC; 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 */ /* ICAP_PIXELTYPE */
static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action) 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; 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"); 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, &current_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) switch (action)
{ {
case MSG_QUERYSUPPORT: case MSG_QUERYSUPPORT:
...@@ -282,32 +372,68 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio ...@@ -282,32 +372,68 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
break; break;
case MSG_GET: case MSG_GET:
twCC = msg_get_enum(pCapability, possible_values, sizeof(possible_values) / sizeof(possible_values[0]), for (possible_value_count = 0; choices && *choices && possible_value_count < 3; choices++)
TWTY_UINT16, activeDS.capXferMech, TWPT_BW); {
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; break;
case MSG_SET: case MSG_SET:
twCC = msg_set(pCapability, &val); twCC = msg_set(pCapability, &val);
if (twCC == TWCC_SUCCESS) if (twCC == TWCC_SUCCESS)
{ {
activeDS.capPixelType = (TW_UINT16) val; if (! pixeltype_to_sane_mode(val, mode, sizeof(mode)))
FIXME("Partial Stub: PIXELTYPE set to %d, but ignored\n", val); 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; break;
case MSG_GETDEFAULT: case MSG_GETDEFAULT:
twCC = set_onevalue(pCapability, TWTY_UINT16, TWPT_BW); twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.defaultPixelType);
break; break;
case MSG_RESET: 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 .. */ /* .. fall through intentional .. */
case MSG_GETCURRENT: case MSG_GETCURRENT:
twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.capPixelType); twCC = set_onevalue(pCapability, TWTY_UINT16, current_pixeltype);
break; break;
} }
#endif
return twCC; return twCC;
} }
......
...@@ -34,6 +34,13 @@ static SANE_Status sane_find_option(SANE_Handle h, const char *option_name, ...@@ -34,6 +34,13 @@ static SANE_Status sane_find_option(SANE_Handle h, const char *option_name,
const SANE_Option_Descriptor *opt; const SANE_Option_Descriptor *opt;
int i; 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); rc = psane_control_option(h, 0, SANE_ACTION_GET_VALUE, &optcount, NULL);
if (rc != SANE_STATUS_GOOD) if (rc != SANE_STATUS_GOOD)
return rc; return rc;
...@@ -78,6 +85,20 @@ SANE_Status sane_option_set_int(SANE_Handle h, const char *option_name, SANE_Int ...@@ -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); 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 sane_option_probe_resolution(SANE_Handle h, const char *option_name, SANE_Int *minval, SANE_Int *maxval, SANE_Int *quant)
{ {
SANE_Status rc; SANE_Status rc;
...@@ -97,4 +118,23 @@ SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, ...@@ -97,4 +118,23 @@ SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name,
return rc; 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 #endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#ifdef SONAME_LIBSANE #ifdef SONAME_LIBSANE
# include <sane/sane.h> # include <sane/sane.h>
# include <sane/saneopts.h>
#define MAKE_FUNCPTR(f) typeof(f) * p##f; #define MAKE_FUNCPTR(f) typeof(f) * p##f;
MAKE_FUNCPTR(sane_init) MAKE_FUNCPTR(sane_init)
...@@ -74,7 +75,8 @@ struct tagActiveDS ...@@ -74,7 +75,8 @@ struct tagActiveDS
#endif #endif
/* Capabilities */ /* Capabilities */
TW_UINT16 capXferMech; /* ICAP_XFERMECH */ TW_UINT16 capXferMech; /* ICAP_XFERMECH */
TW_UINT16 capPixelType; /* ICAP_PIXELTYPE */ BOOL PixelTypeSet;
TW_UINT16 defaultPixelType; /* ICAP_PIXELTYPE */
BOOL XResolutionSet; BOOL XResolutionSet;
TW_FIX32 defaultXResolution; TW_FIX32 defaultXResolution;
BOOL YResolutionSet; BOOL YResolutionSet;
...@@ -221,7 +223,9 @@ HWND ScanningDialogBox(HWND dialog, LONG progress); ...@@ -221,7 +223,9 @@ HWND ScanningDialogBox(HWND dialog, LONG progress);
#ifdef SONAME_LIBSANE #ifdef SONAME_LIBSANE
SANE_Status sane_option_get_int(SANE_Handle h, const char *option_name, SANE_Int *val); 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_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_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 #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment