2023-07-10 07:28:45 +00:00
# ifdef max
# undef max
# endif
# ifdef min
# undef min
# endif
# include <memory>
# include "huagaods.hpp"
//#include "twpp/twglue.hpp"
# include <list>
# include <map>
# if defined(WIN32) || defined(_WIN64) // WIN32
# include <shlobj.h>
# include <Psapi.h>
# include <io.h>
# define mktemp _mktemp
# endif // WIN32
# include <algorithm>
using namespace std ;
# define enum2str(R) #R
# pragma warning(disable: 4700)
using namespace Twpp ;
using namespace std : : placeholders ;
extern HMODULE me_ ;
// WIA COM: IStiUSD & IWiaMiniDrv
//custom define caps enum
enum CapTypeEx : unsigned short {
CAP_TYPE_EX_FILL_BLACK_BKG = 0x8004 ,
CAP_TYPE_EX_ROTATE_BKG_180 = 0x8005 ,
CAP_TYPE_EX_SCREW_DETECT = 0x8006 ,
CAP_TYPE_EX_ENHANCE_COLOR = 0x8007 ,
CAP_TYPE_EX_DARK_SAMPLE = 0x8016 ,
CAP_TYPE_EX_FILL_HOLE = 0x8018 ,
CAP_TYPE_EX_SCREW_DETECT_LEVEL = 0x8021 ,
CAP_TYPE_EX_SHARPEN = 0x8022 ,
CAP_TYPE_EX_HARDWARE_VERSION = 0x8025 ,
CAP_TYPE_EX_RID_RED = 0x8026 ,
CAP_TYPE_EX_FOLD = 0x8037 ,
CAP_TYPE_EX_STAPLE_DETECT = 0x8090 ,
CAP_TYPE_EX_DISCARD_BLANK_RECEIPT = 0x8091 ,
CAP_TYPE_EX_FILL_HOLE_RATIO = 0x8092 ,
CAP_TYPE_EX_FLIP = 0x8094 , // switch front back
CAP_TYPE_EX_RID_RED_HSV = 0x8095 ,
CAP_TYPE_EX_DOGEAR_DETECT = 0x8096 ,
CAP_TYPE_EX_BKG_FILLING_METHOD = 0x8097 ,
CAP_TYPE_EX_EDGE_IDENT = 0x8098 ,
CAP_TYPE_EX_ANTI_NOISE = 0x8099 ,
CAP_TYPE_EX_THRESHOLD = 0x8100 ,
CAP_TYPE_EX_DETACH_NOISE = 0x8101 ,
CAP_TYPE_EX_DETACH_NOISE_THRESHOLD = 0x8102 ,
CAP_TYPE_EX_SIZE_DETECT = 0x8103 ,
CAP_TYPE_EX_POWER_LEVEL = 0x8104 ,
CAP_TYPE_EX_ENCODE = 0x8105 ,
CAP_TYPE_EX_CROP_MODEL = 0x8106 ,
CAP_TYPE_EX_DOGEAR_DIST = 0x8107 ,
CAP_TYPE_EX_IMAGE_SPLIT = 0x8108 ,
CAP_TYPE_EX_FADE_BKG = 0x8109 ,
CAP_TYPE_EX_FADE_BKG_VALUE = 0x8110 ,
CAP_TYPE_EX_TO_BE_SCAN = 0x8111 ,
CAP_TYPE_EX_MULTI_OUT = 0x8112 ,
CAP_TYPE_EX_MULTI_OUT_TYPE = 0x8113 ,
CAP_TYPE_EX_SCAN_WITH_HOLE = 0x8114 ,
CAP_TYPE_EX_IP = 0x8200 ,
} ;
enum / / . twain / first . cfg : [ twain - app ] flow = 0
{
TWAIN_APP_TRANSFER_NORMAL = 0 , // first get head and then bits
TWAIN_APP_TRANSFER_REVERSE , // first get bits and then head
} ;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// entry ...
TWPP_ENTRY ( huagao_ds )
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// utilites ...
// some helper functions to handle capability stuff
# define RETURN_ENUM_DESC(en, v, space) \
if ( v = = space : : en ) \
return # en ;
const char * desc_state ( DsState s , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Closed , s , DsState ) ;
RETURN_ENUM_DESC ( Open , s , DsState ) ;
RETURN_ENUM_DESC ( Enabled , s , DsState ) ;
RETURN_ENUM_DESC ( XferReady , s , DsState ) ;
RETURN_ENUM_DESC ( Xferring , s , DsState ) ;
sprintf ( unk , " %d " , s ) ;
return unk ;
}
const char * desc_data_group ( DataGroup d , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Control , d , DataGroup ) ;
RETURN_ENUM_DESC ( Image , d , DataGroup ) ;
RETURN_ENUM_DESC ( Audio , d , DataGroup ) ;
{
sprintf ( unk , " %d " , d ) ;
return unk ;
}
}
const char * desc_data ( Dat d , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Null , d , Dat ) ;
RETURN_ENUM_DESC ( Capability , d , Dat ) ;
RETURN_ENUM_DESC ( Event , d , Dat ) ;
RETURN_ENUM_DESC ( Identity , d , Dat ) ;
RETURN_ENUM_DESC ( Parent , d , Dat ) ;
RETURN_ENUM_DESC ( PendingXfers , d , Dat ) ;
RETURN_ENUM_DESC ( SetupMemXfer , d , Dat ) ;
RETURN_ENUM_DESC ( SetupFileXfer , d , Dat ) ;
RETURN_ENUM_DESC ( Status , d , Dat ) ;
RETURN_ENUM_DESC ( UserInterface , d , Dat ) ;
RETURN_ENUM_DESC ( XferGroup , d , Dat ) ;
RETURN_ENUM_DESC ( CustomData , d , Dat ) ;
RETURN_ENUM_DESC ( DeviceEvent , d , Dat ) ;
RETURN_ENUM_DESC ( FileSystem , d , Dat ) ;
RETURN_ENUM_DESC ( PassThrough , d , Dat ) ;
RETURN_ENUM_DESC ( Callback , d , Dat ) ;
RETURN_ENUM_DESC ( StatusUtf8 , d , Dat ) ;
RETURN_ENUM_DESC ( Callback2 , d , Dat ) ;
RETURN_ENUM_DESC ( ImageInfo , d , Dat ) ;
RETURN_ENUM_DESC ( ImageLayout , d , Dat ) ;
RETURN_ENUM_DESC ( ImageMemXfer , d , Dat ) ;
RETURN_ENUM_DESC ( ImageNativeXfer , d , Dat ) ;
RETURN_ENUM_DESC ( ImageFileXfer , d , Dat ) ;
RETURN_ENUM_DESC ( CieColor , d , Dat ) ;
RETURN_ENUM_DESC ( GrayResponse , d , Dat ) ;
RETURN_ENUM_DESC ( RgbResponse , d , Dat ) ;
RETURN_ENUM_DESC ( JpegCompression , d , Dat ) ;
RETURN_ENUM_DESC ( Palette8 , d , Dat ) ;
RETURN_ENUM_DESC ( ExtImageInfo , d , Dat ) ;
RETURN_ENUM_DESC ( Filter , d , Dat ) ;
RETURN_ENUM_DESC ( AudioFileXfer , d , Dat ) ;
RETURN_ENUM_DESC ( AudioInfo , d , Dat ) ;
RETURN_ENUM_DESC ( AudioNativeXfer , d , Dat ) ;
RETURN_ENUM_DESC ( IccProfile , d , Dat ) ;
RETURN_ENUM_DESC ( ImageMemFileXfer , d , Dat ) ;
RETURN_ENUM_DESC ( EntryPoint , d , Dat ) ;
{
sprintf ( unk , " %d " , d ) ;
return unk ;
}
}
const char * desc_msg ( Msg m , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Null , m , Msg ) ;
RETURN_ENUM_DESC ( Get , m , Msg ) ;
RETURN_ENUM_DESC ( GetCurrent , m , Msg ) ;
RETURN_ENUM_DESC ( GetDefault , m , Msg ) ;
RETURN_ENUM_DESC ( GetFirst , m , Msg ) ;
RETURN_ENUM_DESC ( GetNext , m , Msg ) ;
RETURN_ENUM_DESC ( Set , m , Msg ) ;
RETURN_ENUM_DESC ( Reset , m , Msg ) ;
RETURN_ENUM_DESC ( QuerySupport , m , Msg ) ;
RETURN_ENUM_DESC ( GetHelp , m , Msg ) ;
RETURN_ENUM_DESC ( GetLabel , m , Msg ) ;
RETURN_ENUM_DESC ( GetLabelEnum , m , Msg ) ;
RETURN_ENUM_DESC ( SetConstraint , m , Msg ) ;
RETURN_ENUM_DESC ( XferReady , m , Msg ) ;
RETURN_ENUM_DESC ( CloseDsReq , m , Msg ) ;
RETURN_ENUM_DESC ( CloseDsOk , m , Msg ) ;
RETURN_ENUM_DESC ( DeviceEvent , m , Msg ) ;
RETURN_ENUM_DESC ( OpenDsm , m , Msg ) ;
RETURN_ENUM_DESC ( CloseDsm , m , Msg ) ;
RETURN_ENUM_DESC ( OpenDs , m , Msg ) ;
RETURN_ENUM_DESC ( CloseDs , m , Msg ) ;
RETURN_ENUM_DESC ( UserSelect , m , Msg ) ;
RETURN_ENUM_DESC ( DisableDs , m , Msg ) ;
RETURN_ENUM_DESC ( EnableDs , m , Msg ) ;
RETURN_ENUM_DESC ( EnableDsUiOnly , m , Msg ) ;
RETURN_ENUM_DESC ( ProcessEvent , m , Msg ) ;
RETURN_ENUM_DESC ( EndXfer , m , Msg ) ;
RETURN_ENUM_DESC ( StopFeeder , m , Msg ) ;
RETURN_ENUM_DESC ( ChangeDir , m , Msg ) ;
RETURN_ENUM_DESC ( CreateDir , m , Msg ) ;
RETURN_ENUM_DESC ( Delete , m , Msg ) ;
RETURN_ENUM_DESC ( FormatMedia , m , Msg ) ;
RETURN_ENUM_DESC ( GetClose , m , Msg ) ;
RETURN_ENUM_DESC ( GetFirstFile , m , Msg ) ;
RETURN_ENUM_DESC ( GetInfo , m , Msg ) ;
RETURN_ENUM_DESC ( GetNextFile , m , Msg ) ;
RETURN_ENUM_DESC ( Rename , m , Msg ) ;
RETURN_ENUM_DESC ( Copy , m , Msg ) ;
RETURN_ENUM_DESC ( AutomaticCaptureDir , m , Msg ) ;
RETURN_ENUM_DESC ( PassThrough , m , Msg ) ;
RETURN_ENUM_DESC ( RegisterCallback , m , Msg ) ;
RETURN_ENUM_DESC ( ResetAll , m , Msg ) ;
RETURN_ENUM_DESC ( CustomBase , m , Msg ) ;
{
sprintf ( unk , " %d " , m ) ;
return unk ;
}
}
const char * desc_return_code ( ReturnCode rc , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Success , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( Failure , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( CheckStatus , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( Cancel , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( DsEvent , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( NotDsEvent , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( XferDone , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( EndOfList , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( InfoNotSupported , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( DataNotAvailable , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( Busy , rc , ReturnCode ) ;
RETURN_ENUM_DESC ( ScannerLocked , rc , ReturnCode ) ;
{
sprintf ( unk , " %d " , rc ) ;
return unk ;
}
}
const char * desc_condition_code ( ConditionCode c , char unk [ 20 ] )
{
RETURN_ENUM_DESC ( Success , c , ConditionCode ) ;
RETURN_ENUM_DESC ( Bummer , c , ConditionCode ) ;
RETURN_ENUM_DESC ( LowMemory , c , ConditionCode ) ;
RETURN_ENUM_DESC ( NoDs , c , ConditionCode ) ;
RETURN_ENUM_DESC ( MaxConnections , c , ConditionCode ) ;
RETURN_ENUM_DESC ( OperationError , c , ConditionCode ) ;
RETURN_ENUM_DESC ( BadCap , c , ConditionCode ) ;
RETURN_ENUM_DESC ( BadProtocol , c , ConditionCode ) ;
RETURN_ENUM_DESC ( BadValue , c , ConditionCode ) ;
RETURN_ENUM_DESC ( SeqError , c , ConditionCode ) ;
RETURN_ENUM_DESC ( BadDest , c , ConditionCode ) ;
RETURN_ENUM_DESC ( CapUnsupported , c , ConditionCode ) ;
RETURN_ENUM_DESC ( CapBadOperation , c , ConditionCode ) ;
RETURN_ENUM_DESC ( CapSeqError , c , ConditionCode ) ;
RETURN_ENUM_DESC ( Denied , c , ConditionCode ) ;
RETURN_ENUM_DESC ( FileExists , c , ConditionCode ) ;
RETURN_ENUM_DESC ( FileNotFound , c , ConditionCode ) ;
RETURN_ENUM_DESC ( NotEmpty , c , ConditionCode ) ;
RETURN_ENUM_DESC ( PaperJam , c , ConditionCode ) ;
RETURN_ENUM_DESC ( PaperDoubleFeed , c , ConditionCode ) ;
RETURN_ENUM_DESC ( FileWriteError , c , ConditionCode ) ;
RETURN_ENUM_DESC ( CheckDeviceOnline , c , ConditionCode ) ;
RETURN_ENUM_DESC ( InterLock , c , ConditionCode ) ;
RETURN_ENUM_DESC ( DamagedCorner , c , ConditionCode ) ;
RETURN_ENUM_DESC ( FocusError , c , ConditionCode ) ;
RETURN_ENUM_DESC ( DocTooLight , c , ConditionCode ) ;
RETURN_ENUM_DESC ( DocTooDark , c , ConditionCode ) ;
RETURN_ENUM_DESC ( NoMedia , c , ConditionCode ) ;
{
sprintf ( unk , " %d " , c ) ;
return unk ;
}
}
template < typename T >
static Result oneValGet ( Msg msg , Capability & data , const T & value ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
data = Capability : : createOneValue ( data . type ( ) , value ) ;
return { } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
static Result oneValGetString ( Msg msg , Capability & data , std : : string value ) {
Str255 str ;
str . setData ( value . c_str ( ) , value . size ( ) ) ;
return oneValGet ( msg , data , str ) ;
}
template < typename T >
static Result enmGet ( Msg msg , Capability & data , const T & value ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration ( data . type ( ) , { value } ) ;
return { } ;
case Msg : : GetCurrent :
case Msg : : GetDefault :
data = Capability : : createOneValue ( data . type ( ) , value ) ;
return { } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T >
static Result oneValGetSet ( Msg msg , Capability & data , T & value , const T & def ) {
switch ( msg ) {
case Msg : : Reset :
value = def ;
// fallthrough
case Msg : : Get :
case Msg : : GetCurrent :
data = Capability : : createOneValue ( data . type ( ) , value ) ;
return { } ;
case Msg : : GetDefault :
data = Capability : : createOneValue ( data . type ( ) , def ) ;
return { } ;
case Msg : : Set :
value = data . currentItem < T > ( ) ;
return { } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T >
static Result oneValGetSetConst ( Msg msg , Capability & data , const T & def ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
case Msg : : Reset :
data = Capability : : createOneValue ( data . type ( ) , def ) ;
return { } ;
case Msg : : Set :
return data . currentItem < T > ( ) = = def ?
Result ( ) : Result ( ReturnCode : : Failure , ConditionCode : : BadValue ) ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T >
static Result enmGetSetConst ( Msg msg , Capability & data , const T & def ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration ( data . type ( ) , { def } ) ;
return { } ;
case Msg : : GetCurrent :
case Msg : : GetDefault :
case Msg : : Reset :
data = Capability : : createOneValue ( data . type ( ) , def ) ;
return { } ;
case Msg : : Set :
return data . currentItem < T > ( ) = = def ?
Result ( ) : Result ( ReturnCode : : Failure , ConditionCode : : BadValue ) ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllReset ( Msg msg , Capability & data , std : : initializer_list < T2 > values , T1 & currvalue , T2 defaultvalue , UInt32 currindex , UInt32 defaultindex ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration < cap > ( values , currindex , defaultindex ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < cap > ( ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < cap > ( defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllReset ( Msg msg , Capability & data , std : : list < T2 > values , T1 & currvalue , T2 defaultvalue , UInt32 currindex , UInt32 defaultindex ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration < cap > ( values , currindex , defaultindex ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < cap > ( ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < cap > ( defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllResetEx ( Msg msg , Capability & data , std : : initializer_list < T2 > values , T1 & currvalue , T2 defaultvalue , UInt32 currindex , UInt32 defaultindex ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration < T2 > ( cap , values , currindex , defaultindex ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < T2 > ( cap , ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < T2 > ( cap , defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllResetEx ( Msg msg , Capability & data , std : : list < T2 > values , T1 & currvalue , T2 defaultvalue , UInt32 currindex , UInt32 defaultindex ) {
switch ( msg ) {
case Msg : : Get :
data = Capability : : createEnumeration < T2 > ( cap , values , currindex , defaultindex ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < T2 > ( cap , ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < T2 > ( cap , defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllReset ( Msg msg , Capability & data , T1 & currvalue , T2 defaultvalue ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
data = Capability : : createOneValue < cap > ( ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < cap > ( defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllResetEx ( Msg msg , Capability & data , T1 & currvalue , T2 defaultvalue ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
data = Capability : : createOneValue < T2 > ( cap , ( T2 ) currvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
currvalue = ( T1 ) defaultvalue ;
data = Capability : : createOneValue < T2 > ( cap , defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T , Twpp : : CapType cap >
Result cap_get_enum_values ( Msg msg , Capability & data , std : : list < T > values , T & cur , T & def , UInt32 cur_ind , UInt32 def_ind )
{
switch ( msg )
{
case Msg : : Get :
data = Capability : : createEnumeration < T > ( cap , values . size ( ) , cur_ind , def_ind ) ;
//data = Capability::createArray<T>(cap, values.size());
{
auto arr = data . enumeration < T > ( ) ;
int i = 0 ;
for ( const auto & v : values )
arr [ i + + ] = v ;
}
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < T > ( cap , cur ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
data = Capability : : createOneValue < T > ( cap , def ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T , Twpp : : CapType cap >
Result cap_get_one_value ( Msg msg , Capability & data , T & cur , T & def , T * lower , T * upper , T * step )
{
switch ( msg )
{
case Msg : : Get :
if ( lower & & upper & & step )
{
data = Capability : : createRange < T > ( cap , * lower , * upper , * step , cur , def ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
}
case Msg : : GetCurrent :
data = Capability : : createOneValue < T > ( cap , cur ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
case Msg : : Reset :
case Msg : : GetDefault :
data = Capability : : createOneValue < T > ( cap , def ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAll ( Msg msg , Capability & data , T1 & currvalue , T2 defaultvalue ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
data = Capability : : createOneValue < cap > ( ( T2 ) defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
template < typename T1 , typename T2 , Twpp : : CapType cap >
Result CapSupGetAllEx ( Msg msg , Capability & data , T1 & currvalue , T2 defaultvalue ) {
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
data = Capability : : createOneValue < cap , T2 > ( defaultvalue ) ;
return { ReturnCode : : Success , ConditionCode : : Success } ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
}
static void copy_type ( Bool & to , bool from )
{
to = from ;
}
static void copy_type ( bool & to , Bool from )
{
to = ( bool ) from ;
}
static void copy_type ( BYTE & to , bool from )
{
to = from ;
}
static void copy_type ( bool & to , BYTE from )
{
to = ( bool ) from ;
}
static void copy_type ( UInt32 & to , int from )
{
to = from ;
}
static void copy_type ( int & to , UInt32 from )
{
to = from ;
}
static void copy_type ( Fix32 & to , double from )
{
to = ( float ) from ;
}
static void copy_type ( Fix32 & to , float from )
{
to = from ;
}
static void copy_type ( float & to , Fix32 from )
{
to = from . toFloat ( ) ;
}
static void copy_type ( Str255 & to , std : : string from )
{
to . setData ( utils : : utf82ansi ( from . c_str ( ) ) . c_str ( ) ) ;
}
static void copy_type ( std : : string & to , Str255 from )
{
2023-07-26 01:07:44 +00:00
to = std : : move ( utils : : ansi2utf8 ( from . data ( ) ) ) ;
2023-07-10 07:28:45 +00:00
}
static void copy_type ( Str64 & to , std : : string from )
{
to . setData ( utils : : utf82ansi ( from . c_str ( ) ) . c_str ( ) ) ;
}
static void copy_type ( std : : string & to , Str64 from )
{
to = std : : move ( utils : : ansi2utf8 ( from . data ( ) ) ) ;
}
template < typename T >
bool list_value_at ( std : : list < T > & lst , int ind , T & t )
{
bool found = false ;
if ( ind > = 0 )
{
typename std : : list < T > : : iterator it = lst . begin ( ) ;
for ( ; it ! = lst . end ( ) ; + + it , - - ind )
{
if ( ind = = 0 )
{
t = * it ;
found = true ;
break ;
}
}
}
return found ;
}
template < typename T >
int distance ( std : : vector < T > & vec , const T & v , int offset = sane_opts : : RANGE_POS_ENUM_BEGIN )
{
return std : : distance ( vec . begin ( ) + offset ,
std : : find ( vec . begin ( ) + offset , vec . end ( ) , v ) ) ;
}
UINT16 bit_depth_from_sane ( int sane )
{
if ( sane = = COLOR_BW )
return 1 ;
else if ( sane = = COLOR_GRAY )
return 8 ;
else if ( sane = = COLOR_RGB )
return 24 ;
else
return /*sane*/ 24 ;
}
static ImageFileFormat from_sane_image_type ( int sane_img_type )
{
ImageFileFormat fmt = ImageFileFormat : : Bmp ;
switch ( sane_img_type )
{
case SANE_IMAGE_TYPE_PNG :
fmt = ImageFileFormat : : Png ;
break ;
case SANE_IMAGE_TYPE_JPG :
fmt = ImageFileFormat : : Jpx ;
break ;
case SANE_IMAGE_TYPE_TIFF :
fmt = ImageFileFormat : : Tiff ;
break ;
case SANE_IMAGE_TYPE_JFIF :
fmt = ImageFileFormat : : Jfif ;
break ;
case SANE_IMAGE_TYPE_WEBP :
break ;
case SANE_IMAGE_TYPE_PDF :
fmt = ImageFileFormat : : Pdf ;
break ;
case SANE_IMAGE_TYPE_GIF :
break ;
case SANE_IMAGE_TYPE_SVG :
break ;
default :
break ;
}
return fmt ;
}
struct
{
Filter twain ;
int sane ;
} g_filter [ ] = { { Filter : : Red , FILTER_RED } , { Filter : : Green , FILTER_GREEN } , { Filter : : Blue , FILTER_BLUE } , { Filter : : None , FILTER_NONE } } ;
Filter from_sane_filter ( int sane )
{
for ( int i = 0 ; i < _countof ( g_filter ) ; + + i )
{
if ( g_filter [ i ] . sane = = sane )
return g_filter [ i ] . twain ;
}
return Filter : : None ;
}
int to_sane_filter ( Filter twain )
{
for ( int i = 0 ; i < _countof ( g_filter ) ; + + i )
{
if ( g_filter [ i ] . twain = = twain )
return g_filter [ i ] . sane ;
}
return FILTER_NONE ;
}
struct
{
Filter twain ;
int sane ;
} g_enhance [ ] = { { Filter : : Red , ENHANCE_RED } , { Filter : : Green , ENHANCE_GREEN } , { Filter : : Blue , ENHANCE_BLUE } , { Filter : : None , ENHANCE_NONE } } ;
Filter from_sane_enhance ( int sane )
{
for ( int i = 0 ; i < _countof ( g_filter ) ; + + i )
{
if ( g_filter [ i ] . sane = = sane )
return g_filter [ i ] . twain ;
}
return Filter : : None ;
}
int to_sane_enhance ( Filter twain )
{
for ( int i = 0 ; i < _countof ( g_filter ) ; + + i )
{
if ( g_filter [ i ] . twain = = twain )
return g_filter [ i ] . sane ;
}
return FILTER_NONE ;
}
float trans_range ( float val , float min_from , float max_from , float min_to , float max_to , bool for_step = false )
{
// transfer val in range [min_from, max_from] to value in range [min_to, max_to]
if ( for_step )
{
val / = max_from - min_from ;
val * = max_to - min_to ;
}
else
{
val - = min_from ;
val / = max_from - min_from ;
val * = max_to - min_to ;
val + = min_to ;
}
return val ;
}
static void log_attr_access ( int attr , int method )
{
const char * op = " Unknown Oper " ;
# define METHOD_DESC(oper) \
if ( method = = ( int ) Msg : : oper ) \
op = # oper ;
METHOD_DESC ( Set )
else METHOD_DESC ( Reset )
else METHOD_DESC ( Get )
else METHOD_DESC ( GetCurrent )
else METHOD_DESC ( GetDefault )
utils : : to_log ( 1 , " %s 0x%04x \r \n " , op , attr ) ;
}
// get fixed-ids from SANE option ...
2023-09-23 08:07:23 +00:00
static SANE_Bool got_fixed_id ( int id , void * param )
2023-07-10 07:28:45 +00:00
{
( ( std : : vector < uint32_t > * ) param ) - > push_back ( id ) ;
2023-09-23 08:07:23 +00:00
return SANE_TRUE ;
2023-07-10 07:28:45 +00:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// huagao_ds ...
# include "../../../sdk/include/huagao/brand.h"
2023-07-20 09:52:33 +00:00
static Identity * srcIdent = nullptr ;
// static Identity* srcIdent = new Identity(
// Version(VERSION_MAIN, VERSION_SUB, Language::English, Country::China, VERSION_STR(VERSION_MAIN, VERSION_SUB, VERSION_BUILD1, VERSION_PATCH)),
// DataGroup::Image, PRODUCT_VENDOR, PRODUCT_FAMILY, Str32(product_twain_name.c_str()));
2023-07-10 07:28:45 +00:00
2023-09-25 05:30:53 +00:00
class my_cleanup
2023-07-20 09:52:33 +00:00
{
2023-09-25 05:30:53 +00:00
public :
my_cleanup ( )
2023-07-20 09:52:33 +00:00
{
Str32 n ;
n . setData ( ( std : : string ( PRODUCT_NAME ) + " TWAIN " ) . c_str ( ) ) ;
srcIdent = new Identity ( Version ( VERSION_MAIN , VERSION_SUB , Language : : English , Country : : China , VERSION_STR ( VERSION_MAIN , VERSION_SUB , VERSION_BUILD1 , VERSION_PATCH ) ) ,
2023-09-25 05:30:53 +00:00
DataGroup : : Image , PRODUCT_VENDOR , PRODUCT_FAMILY , n ) ;
2023-07-20 09:52:33 +00:00
}
2023-09-21 03:23:38 +00:00
~ my_cleanup ( )
{
2023-09-25 05:30:53 +00:00
delete srcIdent ;
2023-09-21 03:23:38 +00:00
srcIdent = nullptr ;
}
} ;
static my_cleanup clear_global_objects_ ;
2023-07-10 07:28:45 +00:00
static std : : once_flag oc ;
huagao_ds : : huagao_ds ( ) : cur_head_ ( NULL ) , dpi_ ( 200 ) , xfer_ready_failed_ ( false ) , log_all_triple_ ( false ) , scanner_status_ ( SCANNER_STATUS_NOT_INIT )
, count_ ( - 1 ) , bUiOnly_ ( false ) , show_setting_ ( false )
{
//std::call_once(oc, [&]() { log4cplus::Initializer(); });
}
huagao_ds : : ~ huagao_ds ( )
{
if ( memoryinfo . get ( ) ) {
m_memoryfalg = false ;
if ( memoryinfo - > joinable ( ) )
memoryinfo - > join ( ) ;
}
if ( cur_head_ )
delete cur_head_ ;
2023-09-21 03:23:38 +00:00
uninitialize_sane ( nullptr ) ;
2023-07-10 07:28:45 +00:00
}
std : : string huagao_ds : : get_hidedlg_path ( void )
{
char szIniFile [ MAX_PATH ] = { 0 } ;
// SHGetSpecialFolderPathA(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
// #ifdef MAKEHUAGAO
// strcat(szIniFile, "\\twain_32\\HuaGoScan\\hidedlg.exe");
// #elif defined AUGE
// strcat(szIniFile, "\\twain_32\\AuGeScan\\hidedlg.exe");
// #elif defined HANVON
// strcat(szIniFile, "\\twain_32\\HanvonScan\\hidedlg.exe");
// #elif defined LANXUM
// strcat(szIniFile, "\\twain_32\\LANXUMSCAN\\hidedlg.exe");
// #else // MAKEHUAGAO
// strcat(szIniFile, "\\twain_32\\ZhibenScan\\hidedlg.exe");
// #endif
return szIniFile ;
}
void huagao_ds : : showmsg ( const char * msg , int err )
{
// ShellExecuteA(NULL, "open", huagao_ds::get_hidedlg_path().c_str(), msg, NULL, SW_HIDE);
}
int huagao_ds : : on_scanner_event ( int ev , void * param )
{
return ( ( huagao_ds * ) param ) - > handle_scanner_event ( ev , false ) ;
}
const Identity & huagao_ds : : defaultIdentity ( ) noexcept {
// remember, we return a reference, therefore the identity must not be placed on the stack of this method
return * srcIdent ;
}
Result huagao_ds : : selectIdentity ( Twpp : : Identity & ident ) noexcept {
// remember, we return a reference, therefore the identity must not be placed on the stack of this method
ident = * srcIdent ;
return success ( ) ;
return { ReturnCode : : Failure , ConditionCode : : NoDs } ;
}
Twpp : : ConditionCode huagao_ds : : condition_code_from_hg_error ( int hgerr )
{
if ( hgerr = = SCANNER_ERR_OK )
return Twpp : : ConditionCode : : Success ;
if ( hgerr = = SCANNER_ERR_DEVICE_NOT_FOUND )
return Twpp : : ConditionCode : : CheckDeviceOnline ;
if ( hgerr = = SCANNER_ERR_IO | | hgerr = = SANE_STATUS_IO_ERROR )
return Twpp : : ConditionCode : : OperationError ;
if ( hgerr = = SCANNER_ERR_OUT_OF_RANGE )
return Twpp : : ConditionCode : : BadCap ;
if ( hgerr = = SCANNER_ERR_DEVICE_NOT_SUPPORT | | hgerr = = SANE_STATUS_UNSUPPORTED )
return Twpp : : ConditionCode : : BadProtocol ;
if ( hgerr = = SCANNER_ERR_INVALID_PARAMETER | | hgerr = = SANE_STATUS_INVAL )
return Twpp : : ConditionCode : : BadValue ;
if ( hgerr = = SCANNER_ERR_ACCESS_DENIED | | hgerr = = SANE_STATUS_ACCESS_DENIED )
return Twpp : : ConditionCode : : Denied ;
if ( hgerr = = SCANNER_ERR_OPEN_FILE_FAILED )
return Twpp : : ConditionCode : : FileNotFound ;
if ( hgerr = = SCANNER_ERR_DEVICE_PAPER_JAMMED | | hgerr = = SANE_STATUS_JAMMED )
return Twpp : : ConditionCode : : PaperJam ;
if ( hgerr = = SCANNER_ERR_DEVICE_DOUBLE_FEEDING )
return Twpp : : ConditionCode : : PaperDoubleFeed ;
if ( hgerr = = SCANNER_ERR_WRITE_FILE_FAILED )
return Twpp : : ConditionCode : : FileWriteError ;
if ( hgerr = = SCANNER_ERR_DEVICE_DOGEAR )
return Twpp : : ConditionCode : : DamagedCorner ;
if ( hgerr = = SCANNER_ERR_DEVICE_NO_PAPER | | hgerr = = SANE_STATUS_NO_DOCS )
return Twpp : : ConditionCode : : NoMedia ;
if ( hgerr = = SCANNER_ERR_OPENED_BY_OTHER_PROCESS )
return Twpp : : ConditionCode : : MaxConnections ;
if ( hgerr = = SCANNER_ERR_INSUFFICIENT_MEMORY | | hgerr = = SANE_STATUS_NO_MEM )
return Twpp : : ConditionCode : : LowMemory ;
if ( hgerr = = SCANNER_ERR_DEVICE_NOT_FOUND )
return Twpp : : ConditionCode : : NoDs ;
return ConditionCode : : Bummer ;
// return (Twpp::ConditionCode)((int)Twpp::ConditionCode::CustomBase + hgerr);
}
Result huagao_ds : : capabilityGet ( const Identity & origin , Capability & data )
{
return capCommon ( origin , Msg : : Get , data ) ;
}
Result huagao_ds : : capabilityGetCurrent ( const Identity & origin , Capability & data )
{
return capCommon ( origin , Msg : : GetCurrent , data ) ;
}
Result huagao_ds : : capabilityGetDefault ( const Identity & origin , Capability & data )
{
return capCommon ( origin , Msg : : GetDefault , data ) ;
}
Result huagao_ds : : capabilityQuerySupport ( const Identity & , Capability & data )
{
auto it = m_query . find ( data . type ( ) ) ;
MsgSupport sup = it ! = m_query . end ( ) ? it - > second : msgSupportEmpty ;
data = Capability : : createOneValue ( data . type ( ) , sup ) ;
return success ( ) ;
}
Result huagao_ds : : capabilityReset ( const Identity & origin , Capability & data )
{
return capCommon ( origin , Msg : : Reset , data ) ;
}
Result huagao_ds : : capabilityResetAll ( const Identity & origin )
{
for ( auto & pair : m_query ) {
if ( ( pair . second & MsgSupport : : Reset ) ! = msgSupportEmpty ) {
Capability dummyCap ( pair . first ) ;
capCommon ( origin , Msg : : Reset , dummyCap ) ;
}
}
return success ( ) ;
}
Result huagao_ds : : capabilitySet ( const Identity & origin , Capability & data )
{
return capCommon ( origin , Msg : : Set , data ) ;
}
Result huagao_ds : : eventProcess ( const Identity & , Event & event )
{
// const MSG* msg = (const MSG*)event.event();
//if (scanner_.get() && show_setting_)
//{
// int ev = scanner_->get_event();
//
// if(ev)
// handle_scanner_event(ev);
//}
/*if (xfer_ready_)
{
notifyXferReady ( ) ;
xfer_ready_ = false ;
}
else */ if ( take_and_reset_notify_close_flag ( ) )
{
notifyCloseCancel ( ) ;
}
event . setMessage ( Msg : : Null ) ;
return { ReturnCode : : NotDsEvent , ConditionCode : : Success } ;
}
Twpp : : Result huagao_ds : : deviceEventGet ( const Twpp : : Identity & origin , Twpp : : DeviceEvent & data )
{
// data = DeviceEvent::simple(load_sane_util::take_event(), "HUAGAO");
// return success();
return seqError ( ) ;
}
Result huagao_ds : : identityOpenDs ( const Identity & id )
{
Identity target ( id ) ;
Result result = huagao_ds : : selectIdentity ( target ) ;
if ( scanner_ . get ( ) )
scanner_ . reset ( ) ;
if ( result . returnCode ( ) ! = ReturnCode : : Success )
{
// load_sane_util::uninitialize();
return result ;
}
int err = 0 , attempt = 0 , max_try = 100 ;
2023-09-22 08:26:22 +00:00
scanner_ . reset ( open_scanner ( PRODUCT_FAMILY , & err ) ) ;
2023-07-10 07:28:45 +00:00
if ( ! scanner_ . get ( ) )
{
2023-07-21 08:56:28 +00:00
utils : : to_log ( 3 , " OpenDS(%s) error: %d \r \n " , PRODUCT_FAMILY , err ) ;
2023-07-10 07:28:45 +00:00
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( err ) } ;
}
// ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str()));
scanner_ - > set_event_callback ( & huagao_ds : : on_scanner_event , this ) ;
if ( get_config_number ( " twain-app " , " flow " ) = = TWAIN_APP_TRANSFER_REVERSE )
{
cur_head_ = new SANE_Parameters ;
memset ( cur_head_ , 0 , sizeof ( SANE_Parameters ) ) ;
}
log_all_triple_ = get_config_number ( " twain-app " , " log-all-triple " ) = = 1 ;
notify_close_ = get_config_number ( " twain-app " , " notify-close " ) ;
double_check_mode_ = get_config_number ( " twain-app " , " double-check " ) ;
if ( double_check_mode_ = = 0 )
{
char pe [ MAX_PATH ] = { 0 } , * name = NULL ;
GetModuleFileNameA ( NULL , pe , _countof ( pe ) - 1 ) ;
name = strrchr ( pe , ' \\ ' ) ;
if ( name + + = = NULL )
name = pe ;
if ( STRICMP ( name , " \u597D \u5206 \u6570 \u9605 \u5377 \u626B \u63CF \u7AEF .exe " ) = = 0 )
double_check_mode_ = DOUBLE_CHECK_ULTRASONIC ;
else
double_check_mode_ = DOUBLE_CHECK_TWAIN ;
}
utils : : to_log ( 1 , " Double check mode = %d \r \n " , double_check_mode_ ) ;
2023-07-26 01:07:44 +00:00
int nobd = get_config_number ( " twain-app " , " no-bitdepth " , 0 , - 1 ) ;
if ( nobd = = - 1 )
{
char pe [ MAX_PATH ] = { 0 } , * name = NULL ;
GetModuleFileNameA ( NULL , pe , _countof ( pe ) - 1 ) ;
name = strrchr ( pe , ' \\ ' ) ;
if ( name + + = = NULL )
name = pe ;
if ( STRICMP ( name , " \u519B \u961F \u626B \u63CF 2.0.exe " ) = = 0 ) // 军队扫描2.0.exe
nobd = 1 ;
else
nobd = 0 ;
}
no_bitdepth_ = nobd = = 1 ;
2023-07-26 02:39:07 +00:00
utils : : to_log ( LOG_LEVEL_DEBUG , " BitDepth protocol disabled = %d \r \n " , nobd ) ;
2023-07-26 01:07:44 +00:00
2023-07-10 07:28:45 +00:00
m_compression = Compression : : None ;
2023-09-22 08:26:22 +00:00
init_support_caps ( err ) ;
2023-07-10 07:28:45 +00:00
m_fileXfer . setFormat ( ImageFileFormat : : Bmp ) ;
scanner_status_ = SCANNER_STATUS_READY ;
2023-07-11 09:13:28 +00:00
utils : : log_mem_info ( " srcIdent: " , srcIdent , sizeof ( * srcIdent ) ) ;
2023-09-22 08:26:22 +00:00
err = 0 ;
return err = = 0 ? success ( ) : Result ( ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( err ) ) ;
2023-07-10 07:28:45 +00:00
}
Result huagao_ds : : identityCloseDs ( const Identity & )
{
if ( notify_close_thread_ . get ( ) & & notify_close_thread_ - > joinable ( ) )
notify_close_thread_ - > join ( ) ;
// ui_.reset();
if ( scanner_ . get ( ) )
{
scanner_ - > set_event_callback ( ) ;
scanner_ - > ui_hide ( ) ;
scanner_ . reset ( ) ;
}
// load_sane_util::uninitialize();
scanner_status_ = SCANNER_STATUS_NOT_INIT ;
return success ( ) ;
}
Result huagao_ds : : pendingXfersGet ( const Identity & , PendingXfers & data )
{
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
// <20> <> ʾ <EFBFBD> <CABE> <EFBFBD> ý<EFBFBD> <C3BD> <EFBFBD> ʱ<EFBFBD> <CAB1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> EndXfer<65> <72> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> <D2BB> ͼƬ<CDBC> <C6AC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ʾ <EFBFBD> <CABE> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> <DAB4> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
int cnt = get_scanned_image_count ( - 1 ) ;
// FIX-2023-05-29: <20> Ƿ<C7B7> <F1B1A3B3> <EFBFBD> <EFBFBD> ý<EFBFBD> <C3BD> <EFBFBD> <EFBFBD> <EFBFBD> ʾ <EFBFBD> <CABE> <EFBFBD> <EFBFBD> APP<50> <50> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˴ <EFBFBD> <CBB4> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> <C7B7> <EFBFBD> ʾ UI<55> <49> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> <D2BB> ɨ<EFBFBD> <C9A8> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
//int cnt = show_setting_ ? 1 : get_scanned_image_count(-1);
data . setCount ( cnt ) ;
return success ( ) ;
}
Result huagao_ds : : pendingXfersEnd ( const Identity & id , PendingXfers & data )
{
2023-08-04 05:13:36 +00:00
// complete transferring of current image ...
pending_xfer_ . clear ( ) ;
if ( scanner_ . get ( ) )
{
scanner_ - > discard_first_image ( ) ;
}
2023-07-10 07:28:45 +00:00
return pendingXfersGet ( id , data ) ;
}
Result huagao_ds : : pendingXfersReset ( const Identity & id , PendingXfers & data )
{
pending_xfer_ . clear ( ) ;
2023-08-04 05:13:36 +00:00
if ( scanner_ . get ( ) )
{
scanner_ - > stop ( ) ;
while ( scanner_ - > discard_first_image ( ) ) ;
}
data . setCount ( 0 ) ;
2023-07-10 07:28:45 +00:00
2023-08-04 05:13:36 +00:00
return success ( ) ;
//return pendingXfersGet(id, data);
2023-07-10 07:28:45 +00:00
}
Result huagao_ds : : setupMemXferGet ( const Identity & id , SetupMemXfer & data )
{
SANE_Parameters head ;
size_t total = 0 ;
DWORD to = cur_head_ ? - 1 : 0 ;
if ( ! scanner_ . get ( ) | | get_scanned_image_count ( to ) = = 0 )
{
if ( cur_head_ )
{
UserInterface ui ( FALSE , FALSE , ( Twpp : : Handle ) 0 ) ;
data . setPreferredSize ( 1 ) ;
call ( id , DataGroup : : Control , Dat : : UserInterface , Msg : : DisableDs , & ui ) ;
}
else
{
int def_w = 2000 ,
def_h = 6000 ;
data . setMinSize ( def_w * 3 /* * def_h*/ ) ;
data . setPreferredSize ( def_w * 3 * def_h ) ;
data . setMaxSize ( def_w * 3 * def_h ) ;
}
return success ( ) ;
}
if ( scanner_ - > get_first_image_header ( & head , & total ) )
{
if ( m_compression = = Compression : : None )
{
int line_bytes = ( head . bytes_per_line + 3 ) / 4 * 4 ;
data . setMinSize ( head . bytes_per_line ) ;
data . setPreferredSize ( line_bytes * head . lines ) ;
data . setMaxSize ( line_bytes * head . lines ) ;
}
else
{
data . setMinSize ( total ) ;
data . setPreferredSize ( total ) ;
data . setMaxSize ( total ) ;
}
return success ( ) ;
}
else
return badValue ( ) ;
}
Result huagao_ds : : userInterfaceDisable ( const Identity & , UserInterface & ui )
{
if ( scanner_ . get ( ) )
{
scanner_ - > stop ( ) ;
scanner_ - > ui_hide ( ) ;
}
return success ( ) ;
}
Result huagao_ds : : userInterfaceEnable ( const Identity & , UserInterface & ui )
{
notfify_close_ = false ;
bUiOnly_ = false ;
show_setting_ = false ;
scanner_ - > twain_set_transfer ( ( twain_xfer ) m_capXferMech ) ;
2023-07-18 06:13:43 +00:00
if ( ! ui . showUi ( ) | | ! scanner_ - > ui_is_ok ( ) )
2023-07-10 07:28:45 +00:00
{
2023-07-20 09:10:31 +00:00
if ( scanner_ - > ui_is_ok ( ) )
scanner_ - > ui_show_progress ( ( HWND ) ui . parent ( ) . raw ( ) , m_bIndicator ) ;
else
2023-07-18 06:13:43 +00:00
utils : : to_log ( LOG_LEVEL_WARNING , " APP want to show setting UI, but UI is not in service! \n " ) ;
2023-07-10 07:28:45 +00:00
xfer_ready_failed_ = false ;
scanner_status_ = SCANNER_STATUS_SCAN_1 ;
app_trigger_event_ = false ;
int err = scanner_ - > start ( ) ;
if ( err = = SCANNER_ERR_OK )
{
return success ( ) ;
}
else
{
scanner_status_ = SCANNER_STATUS_READY ;
// if (err == SCANNER_ERR_DEVICE_NO_PAPER)
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( err ) } ;
return bummer ( ) ;
}
}
return showTwainUI ( ui ) ;
}
Result huagao_ds : : userInterfaceEnableUiOnly ( const Identity & , UserInterface & ui )
{
// as a minimal source, we do not support GUI that just saves settings
2023-07-20 09:10:31 +00:00
if ( ! scanner_ - > ui_is_ok ( ) )
return bummer ( ) ;
2023-07-10 07:28:45 +00:00
return showTwainUI ( ui , true ) ;
}
Twpp : : Result huagao_ds : : extImageInfoGet ( const Identity & origin , ExtImageInfo & data )
{
for ( int i = 0 ; i < data . size ( ) ; + + i )
{
InfoId id = data . at ( i ) . id ( ) ;
Twpp : : Info & info = data . at ( i ) ;
if ( id = = InfoId : : BarCodeCount )
{
info . allocSimple ( Type : : UInt32 ) ;
* info . items < Twpp : : InfoId : : BarCodeCount > ( ) [ 0 ] . data ( ) = 0 ;
}
else if ( id = = InfoId : : BarCodeType )
{
info . allocSimple ( Type : : UInt32 ) ;
* info . items < Twpp : : InfoId : : BarCodeType > ( ) [ 0 ] . data ( ) = BarCodeType : : ThreeOfNine ;
}
else if ( id = = InfoId : : BarCodeTextLength )
{
info . allocSimple ( Type : : UInt32 ) ;
* info . items < Twpp : : InfoId : : BarCodeTextLength > ( ) [ 0 ] . data ( ) = 0 ;
}
else if ( id = = InfoId : : BarCodeText )
{
//info.allocSimple(Type::Str255, 1);
//info.items<Twpp::InfoId::PrinterText>()[0].data()->setData(std::to_string(6922868285266 + i).c_str());
}
else
info . setReturnCode ( ReturnCode : : InfoNotSupported ) ;
}
return success ( ) ;
return { ReturnCode : : Failure , ConditionCode : : NoMedia } ;
}
Result huagao_ds : : imageInfoGet ( const Identity & , ImageInfo & data )
{
SANE_Parameters head ;
bool ok = false ;
int res = 200 ;
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
if ( cur_head_ & & cur_head_ - > lines )
{
memcpy ( & head , cur_head_ , sizeof ( head ) ) ;
ok = true ;
cur_head_ - > lines = 0 ;
res = dpi_ ;
}
else
{
//if (!scanner_->wait_image())
//{
//// notifyCloseOk();
// return success(); // 好分数需要返回成<E59B9E> ?
//}
if ( get_scanned_image_count ( - 1 ) > 0 ) // 显示设置界面时, 不能阻塞在EndXfer, 否则最后一张图片传输后显示不出来, 故在此做阻塞调用
{
ok = scanner_ - > get_first_image_header ( & head , NULL , & res ) ;
if ( ok )
dpi_ = res ;
}
}
if ( ok )
{
if ( head . format = = SANE_FRAME_RGB )
{
data . setBitsPerPixel ( head . depth * 3 ) ;
data . setSamplesPerPixel ( 3 ) ;
data . bitsPerSample ( ) [ 0 ] = data . bitsPerSample ( ) [ 1 ] = data . bitsPerSample ( ) [ 2 ] = head . depth ;
}
else
{
data . setSamplesPerPixel ( 1 ) ;
data . setBitsPerPixel ( head . depth ) ;
data . bitsPerSample ( ) [ 0 ] = head . depth ;
}
data . setHeight ( head . lines ) ;
if ( m_compression = = Compression : : Group4 )
data . setPixelType ( PixelType : : BlackWhite ) ;
else
{
if ( head . format = = SANE_FRAME_RGB )
data . setPixelType ( PixelType : : Rgb ) ;
else if ( head . format = = SANE_FRAME_GRAY )
data . setPixelType ( head . depth = = 1 ? PixelType : : BlackWhite : PixelType : : Gray ) ;
}
data . setPlanar ( false ) ;
data . setWidth ( head . pixels_per_line ) ;
data . setXResolution ( ( float ) res ) ;
data . setYResolution ( ( float ) res ) ;
data . compression ( m_compression ) ;
}
else
{
2023-09-25 05:30:53 +00:00
utils : : to_log ( LOG_LEVEL_DEBUG , " imageInfoGet = false, error = 0x%x \r \n " , scanner_ - > last_error ( ) ) ;
2023-07-10 07:28:45 +00:00
data . setHeight ( 0 ) ;
2023-09-25 05:30:53 +00:00
//return { ReturnCode::XferDone, ConditionCode::Bummer };
return { ReturnCode : : Failure , condition_code_from_hg_error ( scanner_ - > last_error ( ) ) } ;
2023-07-10 07:28:45 +00:00
}
2023-08-03 06:05:11 +00:00
2023-07-10 07:28:45 +00:00
int h = data . height ( ) ;
int w = data . width ( ) ;
int bitsPerPixel = data . bitsPerPixel ( ) ;
Compression compression = data . compression ( ) ;
PixelType pixelType = data . pixelType ( ) ;
bool planar = data . planar ( ) ;
2023-08-03 06:05:11 +00:00
utils : : to_log ( LOG_LEVEL_DEBUG , " imageInfoGet = (%d * %d * %d), %dDPI \r \n " , w , h , bitsPerPixel , res ) ;
2023-07-10 07:28:45 +00:00
return success ( ) ;
}
Result huagao_ds : : imageLayoutGet ( const Identity & , ImageLayout & data )
{
SANE_Parameters head ;
memset ( & head , 0 , sizeof ( head ) ) ;
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
else if ( get_scanned_image_count ( - 1 ) = = 0 )
return { ReturnCode : : Failure , condition_code_from_hg_error ( scanner_ - > last_error ( ) ) } ;
int res = 200 ;
scanner_ - > get_first_image_header ( & head , NULL , & res ) ;
data . setDocumentNumber ( 1 ) ;
data . setFrameNumber ( 1 ) ;
data . setPageNumber ( 1 ) ;
data . setFrame ( Frame ( 0 , 0 , static_cast < float > ( head . pixels_per_line ) / res , static_cast < float > ( head . lines ) / res ) ) ;
return success ( ) ;
}
Result huagao_ds : : imageLayoutGetDefault ( const Identity & origin , ImageLayout & data )
{
return imageLayoutGet ( origin , data ) ;
}
Result huagao_ds : : imageLayoutSet ( const Identity & origin , ImageLayout & lay )
{
// we dont support setting image frame
ImageLayout def ;
imageLayoutGetDefault ( origin , def ) ;
return lay . frame ( ) = = def . frame ( ) ? success ( ) : badValue ( ) ;
}
Result huagao_ds : : imageLayoutReset ( const Identity & origin , ImageLayout & data )
{
return imageLayoutGet ( origin , data ) ;
}
Result huagao_ds : : imageMemXferGet ( const Identity & origin , ImageMemXfer & data )
{
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
if ( get_scanned_image_count ( - 1 ) = = 0 & & ! pending_xfer_ . img )
{
//if (!cur_head_ || !scanner_->wait_image())
//{
// notifyCloseOk();
// return seqError();
//}
return { ReturnCode : : Failure , condition_code_from_hg_error ( scanner_ - > last_error ( ) ) } ;
}
2023-08-04 09:53:08 +00:00
IScanImg * img = pending_xfer_ . img ? pending_xfer_ . img : scanner_ - > take_first_image ( TWAIN_XFER_Memory ) ;
2023-07-10 07:28:45 +00:00
unsigned long long off = pending_xfer_ . img ? pending_xfer_ . off : img - > get_bits_offset ( ) ;
2023-08-04 09:53:08 +00:00
unsigned char * dst = ( unsigned char * ) data . memory ( ) . data ( ) . data ( ) ;
2023-07-10 07:28:45 +00:00
UInt32 buf_l = data . memory ( ) . size ( ) ;
unsigned int line_l = img - > line_bytes ( ) ,
2023-08-04 09:53:08 +00:00
rows = data . memory ( ) . size ( ) / line_l ;
2023-07-10 07:28:45 +00:00
size_t want_read = rows * line_l ;
Result ret = { ReturnCode : : XferDone , ConditionCode : : Success } ;
if ( rows = = 0 )
return badValue ( ) ;
2023-08-04 09:53:08 +00:00
else if ( want_read > img - > bytes ( ) - off )
{
want_read = img - > bytes ( ) - off ;
rows = ( want_read + line_l - 1 ) / line_l ;
}
2023-07-10 07:28:45 +00:00
if ( pending_xfer_ . img )
{
img - > add_ref ( ) ;
pending_xfer_ . clear ( ) ;
}
2023-08-04 09:53:08 +00:00
else if ( cur_head_ )
2023-07-10 07:28:45 +00:00
{
img - > copy_header ( cur_head_ ) ;
}
data . setBytesPerRow ( line_l ) ;
data . setColumns ( img - > width ( ) ) ;
data . setRows ( rows ) ;
data . setXOffset ( 0 ) ;
2023-08-04 09:53:08 +00:00
data . setYOffset ( UInt32 ( ( off - img - > get_bits_offset ( ) ) / line_l ) ) ;
2023-07-10 07:28:45 +00:00
data . setCompression ( m_compression ) ;
if ( m_compression ! = Compression : : None )
{
want_read = img - > bytes ( ) - off ;
if ( buf_l < want_read )
{
want_read = buf_l ;
}
img - > read ( dst , & want_read , off ) ;
data . setBytesWritten ( want_read ) ;
off + = want_read ;
if ( off < img - > bytes ( ) )
{
pending_xfer_ . img = img ;
pending_xfer_ . off = ( unsigned int ) off ;
img - > add_ref ( ) ;
ret = success ( ) ;
}
else
scanner_ - > image_fetched ( img ) ;
}
else if ( img - > read ( dst , & want_read , off ) = = SCANNER_ERR_OK )
{
want_read / = line_l ;
2023-08-04 09:53:08 +00:00
// data.setRows(want_read);
2023-07-10 07:28:45 +00:00
want_read * = line_l ;
data . setBytesWritten ( want_read ) ;
off + = want_read ;
if ( off < img - > bytes ( ) )
{
pending_xfer_ . img = img ;
pending_xfer_ . off = ( unsigned int ) off ;
img - > add_ref ( ) ;
ret = success ( ) ;
}
else
scanner_ - > image_fetched ( img ) ;
}
else
{
ret = { ReturnCode : : XferDone , ConditionCode : : Bummer } ;
}
img - > release ( ) ;
return ret ;
}
Result huagao_ds : : imageNativeXferGet ( const Identity & id , ImageNativeXfer & data )
{
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
else if ( get_scanned_image_count ( - 1 ) = = 0 )
{
return { ReturnCode : : Failure , condition_code_from_hg_error ( scanner_ - > last_error ( ) ) } ;
}
IScanImg * img = scanner_ - > take_first_image ( TWAIN_XFER_Native ) ;
if ( ! img )
return seqError ( ) ;
if ( data )
data . release ( ) ;
data = ImageNativeXfer ( img - > bytes ( ) ) ;
unsigned long long off = sizeof ( BITMAPFILEHEADER ) ;
unsigned int total = img - > bytes ( ) - off ;
unsigned char * src = img - > data ( off , & total ) ,
* dst = data . data < unsigned char > ( ) . data ( ) ;
while ( off < img - > bytes ( ) & & src )
{
std : : copy ( src , src + total , dst ) ;
dst + = total ;
off + = total ;
if ( off > = img - > bytes ( ) )
break ;
total = img - > bytes ( ) - ( unsigned int ) off ;
src = img - > data ( off , & total ) ;
}
scanner_ - > image_fetched ( img ) ;
img - > release ( ) ;
return { ReturnCode : : XferDone , ConditionCode : : Success } ;
}
Twpp : : Result huagao_ds : : pendingXfersStopFeeder ( const Identity & origin , PendingXfers & data )
{
if ( scanner_ . get ( ) )
scanner_ - > stop ( ) ;
return success ( ) ;
}
Twpp : : Result huagao_ds : : imageFileXferGet ( const Twpp : : Identity & origin )
{
// assume that the file format has set before start-scanning, so we write-down the image content to file directly here ...
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
else if ( get_scanned_image_count ( - 1 ) = = 0 )
return { ReturnCode : : Failure , condition_code_from_hg_error ( scanner_ - > last_error ( ) ) } ;
IScanImg * img = scanner_ - > take_first_image ( TWAIN_XFER_File ) ;
Twpp : : Result ret = seqError ( ) ;
FILE * dst = NULL ;
if ( img )
{
std : : string file ( img - > file ( ) ) ;
int cv_e = 0 ,
status = img - > image_status ( ) ;
if ( file . empty ( ) )
{
dst = fopen ( m_fileXfer . filePath ( ) . string ( ) . c_str ( ) , " wb " ) ;
ret = { ReturnCode : : Failure , ConditionCode : : FileWriteError } ;
if ( dst )
{
unsigned long long off = 0 ;
unsigned int total = img - > bytes ( ) ;
unsigned char * src = img - > data ( off , & total ) ;
while ( src )
{
if ( fwrite ( src , 1 , total , dst ) ! = total )
break ;
off + = total ;
if ( off > = img - > bytes ( ) )
{
ret = Result ( ReturnCode : : XferDone , ConditionCode : : Success ) ;
break ;
}
total = img - > bytes ( ) - ( unsigned int ) off ;
src = img - > data ( off , & total ) ;
}
fclose ( dst ) ;
scanner_ - > image_fetched ( img ) ;
}
else
{
std : : string f ( " CreateFile( " + m_fileXfer . filePath ( ) . string ( ) ) ;
char msg [ 128 ] = { 0 } ;
sprintf ( msg , " ) = %d \r \n " , GetLastError ( ) ) ;
f + = msg ;
utils : : log_info ( f . c_str ( ) , 3 ) ;
}
img - > release ( ) ;
}
else
{
utils : : log_info ( ( " Map file to " + m_fileXfer . filePath ( ) . string ( ) + " \r \n " ) . c_str ( ) , 1 ) ;
img - > keep_file ( true ) ;
scanner_ - > image_fetched ( img ) ;
img - > release ( ) ;
cv_e = utils : : move_file ( file . c_str ( ) , m_fileXfer . filePath ( ) . string ( ) . c_str ( ) ) ;
if ( cv_e = = 0 )
ret = Result ( ReturnCode : : XferDone , ConditionCode : : Success ) ;
else
remove ( file . c_str ( ) ) ;
}
if ( ret . status ( ) = = ConditionCode : : Success & & m_fileXfer . format ( ) ! = ImageFileFormat : : Bmp )
{
SANE_ImageFormatConvert conv ;
std : : string target ( m_fileXfer . filePath ( ) . string ( ) . c_str ( ) ) ;
memset ( & conv , 0 , sizeof ( conv ) ) ;
file = target + " .src " ;
conv . src . fmt . img_format = SANE_IMAGE_TYPE_BMP ;
conv . src . is_file = SANE_TRUE ;
conv . src . data = file . c_str ( ) ;
conv . src . data_len = file . length ( ) ;
conv . dst . fmt . img_format = ( SANE_ImageType ) m_fileXfer . format ( ) ;
conv . dst . fmt . compress . compression = ( SANE_CompressionType ) m_compression ;
conv . dst . fmt . compress . detail = ( void * ) 0 ;
conv . dst . fmt . detail = ( void * ) m_jpegQuality ;
conv . dst . is_file = SANE_TRUE ;
conv . dst . data = target . c_str ( ) ;
conv . dst . data_len = target . length ( ) ;
while ( rename ( target . c_str ( ) , file . c_str ( ) ) )
{
if ( cv_e = = 0 )
{
std : : string info ( " [convert image format] Move ' " ) ;
char buf [ 80 ] = { 0 } ;
sprintf ( buf , " %d \r \n " , GetLastError ( ) ) ;
info + = target + " ' to ' " + file + " ' failed: " ;
utils : : log_info ( ( info + buf ) . c_str ( ) , 3 ) ;
}
if ( + + cv_e > = 9 )
break ;
Sleep ( 30 ) ;
}
if ( cv_e < 9 )
{
cv_e = scanner_ - > convert_image ( & conv ) ;
if ( cv_e ! = SCANNER_ERR_OK )
ret = { ReturnCode : : Failure , ConditionCode : : OperationError } ;
remove ( file . c_str ( ) ) ;
}
}
//if (ret.status() == ConditionCode::Success)
//{
// switch (status)
// {
// case SANE_Image_Statu_Blank:
// break;
// case SANE_Image_Statu_Double:
// ret.setStatus(ConditionCode::PaperDoubleFeed);
// break;
// case SANE_Image_Statu_Jammed:
// ret.setStatus(ConditionCode::PaperJam);
// break;
// }
//}
{
2023-10-20 07:21:17 +00:00
utils : : to_log ( LOG_LEVEL_DEBUG , " FileTransfer '%s' = %d(%d) \r \n " , m_fileXfer . filePath ( ) . string ( ) . c_str ( ) , ( CC ) ret . status ( ) , cv_e ) ;
2023-07-10 07:28:45 +00:00
}
}
return ret ;
}
Twpp : : Result huagao_ds : : setupFileXferGet ( const Twpp : : Identity & origin , Twpp : : SetupFileXfer & data )
{
data . setFilePath ( m_fileXfer . filePath ( ) ) ;
data . setFormat ( m_fileXfer . format ( ) ) ;
return success ( ) ;
}
Twpp : : Result huagao_ds : : setupFileXferGetDefault ( const Twpp : : Identity & origin , Twpp : : SetupFileXfer & data )
{
Str255 str ( " HGTwain.bmp " ) ;
data . setFilePath ( str ) ;
data . setFormat ( ImageFileFormat : : Bmp ) ;
return success ( ) ;
}
Twpp : : Result huagao_ds : : setupFileXferSet ( const Twpp : : Identity & origin , Twpp : : SetupFileXfer & data )
{
m_fileXfer . setFilePath ( data . filePath ( ) ) ;
m_fileXfer . setFormat ( data . format ( ) ) ;
return success ( ) ;
}
Twpp : : Result huagao_ds : : setupFileXferReset ( const Twpp : : Identity & origin , Twpp : : SetupFileXfer & data )
{
m_fileXfer . setFormat ( Twpp : : ImageFileFormat : : Bmp ) ;
std : : string templateName = " HG " ;
char * tempPath = mktemp ( ( char * ) templateName . c_str ( ) ) ;
if ( tempPath ) {
Str255 str ;
str . setData ( tempPath , strlen ( tempPath ) ) ;
m_fileXfer . setFilePath ( str ) ;
return success ( ) ;
}
return badProtocol ( ) ;
}
Result huagao_ds : : call ( const Identity & origin , DataGroup dg , Dat dat , Msg msg , void * data ) {
try {
// we can override almost anything from SourceFromThis, even the top-most source instance call
//FileTools::write_log("D:\\1.txt", "call:datagroup-"+to_string((int)dg)+"dat-"+to_string(int(dat))+"msg-"+to_string(int(msg)));
Result rt ;
char dgs [ 20 ] = { 0 } , dts [ 20 ] = { 0 } , ms [ 20 ] = { 0 } , ss [ 20 ] = { 0 } , rcs [ 20 ] = { 0 } , cs [ 20 ] = { 0 } ;
//trigger_ProcessEvent(dg, dat, msg); // some APPs may be not trigger (Control, Event, ProcessEvent), we help them :( ... // 云阅卷扫描端不等状态改变, 直接取图, 此处设置一次状<E6ACA1> ?2022-11-07
rt = Base : : call ( origin , dg , dat , msg , data ) ;
if ( log_all_triple_ | | ( ( int ) rt . returnCode ( ) & & rt . returnCode ( ) ! = ReturnCode : : NotDsEvent ) )
{
if ( dat = = Dat : : Capability )
{
Twpp : : Capability & cap = * ( Twpp : : Capability * ) data ;
utils : : to_log ( 7 , " [%x - %s]DSEntry(%s, %s.%x, %s) = {%s, %s} \r \n " , GetCurrentThreadId ( ) , desc_state ( state ( ) , ss ) ,
desc_data_group ( dg , dgs ) , desc_data ( dat , dts ) , ( int ) cap . type ( ) , desc_msg ( msg , ms ) , desc_return_code ( rt , rcs ) , desc_condition_code ( ( ConditionCode ) ( Status ) rt , cs ) ) ;
}
else
utils : : to_log ( 7 , " [%x - %s]DSEntry(%s, %s, %s) = {%s, %s} \r \n " , GetCurrentThreadId ( ) , desc_state ( state ( ) , ss ) ,
desc_data_group ( dg , dgs ) , desc_data ( dat , dts ) , desc_msg ( msg , ms ) , desc_return_code ( rt , rcs ) , desc_condition_code ( ( ConditionCode ) ( Status ) rt , cs ) ) ;
if ( ( int ) rt . returnCode ( ) & & rt . returnCode ( ) ! = ReturnCode : : NotDsEvent )
{
bool changed = false ;
if ( dat = = Dat : : PendingXfers & & Msg : : Reset = = msg & & scanner_status_ = = SCANNER_STATUS_STOPPED ) // PurvarScannerForHomework.exe - move modifying from EndXfer to xfer::Reset
{
changed = true ;
rt = success ( ) ;
}
else if ( rt . status ( ) = = ConditionCode : : SeqError )
{
if ( dat = = Dat : : ImageInfo & & Msg : : Get = = msg & & scanner_status_ = = SCANNER_STATUS_STOPPED ) // for demo.exe
{
changed = true ;
rt = { ReturnCode : : Success , ConditionCode : : Bummer } ;
}
else if ( dat = = Dat : : PendingXfers & & Msg : : EndXfer = = msg & & scanner_status_ = = SCANNER_STATUS_STOPPED ) // for photoshop.exe
{
// PendingXfers& data
( static_cast < PendingXfers * > ( data ) ) - > setCount ( 0 ) ;
changed = true ;
rt = { ReturnCode : : Success , ConditionCode : : Success } ;
}
}
else if ( rt . status ( ) = = ConditionCode : : Bummer & & rt . returnCode ( ) = = ReturnCode : : XferDone & & scanner_status_ = = SCANNER_STATUS_STOPPED ) // for demo.exe
{
changed = true ;
rt = { ReturnCode : : Success , ConditionCode : : Bummer } ;
}
if ( changed )
utils : : to_log ( 7 , " modify result to {%s, %s}. \r \n " , desc_return_code ( rt , rcs ) , desc_condition_code ( ( ConditionCode ) ( Status ) rt , cs ) ) ;
}
}
return rt ;
}
catch ( const CapabilityException & e ) {
//FileTools::writelog(log_ERROR, e.what());
//UNREFERENCED_PARAMETER(e);
return badValue ( ) ;
}
}
Result huagao_ds : : customDataGet ( const Twpp : : Identity & origin , Twpp : : CustomData & data )
{
// get user setting from local file ...
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
char * buf = NULL ;
size_t len = 0 ;
if ( scanner_ - > twain_get_config ( buf , & len ) = = SCANNER_ERR_INSUFFICIENT_MEMORY )
{
data = CustomData ( len ) ;
buf = data . lock < char > ( ) ;
scanner_ - > twain_get_config ( buf , & len ) ;
}
return success ( ) ;
}
Result huagao_ds : : customDataSet ( const Twpp : : Identity & origin , Twpp : : CustomData & data )
{
// write user setting to local file ...
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
char * buf = data . lock < char > ( ) ;
scanner_ - > twain_set_config ( buf , data . size ( ) ) ;
return success ( ) ;
}
void huagao_ds : : CapabilityPrintf ( Twpp : : Msg msg , std : : string capability , std : : string value )
{
}
Result huagao_ds : : capCommon ( const Identity & , Msg msg , Capability & data ) {
auto it = m_caps . find ( data . type ( ) ) ;
if ( it ! = m_caps . end ( ) ) {
int type = ( int ) data . type ( ) ;
while ( org_func_ . count ( type ) )
type = org_func_ [ type ] ;
return ( it - > second ) ( ( Twpp : : CapType ) type , msg , data ) ;
}
return capUnsupported ( ) ;
}
Twpp : : Result huagao_ds : : showTwainUI ( Twpp : : UserInterface & data , bool bUiOnly )
{
if ( ! scanner_ - > is_online ( ) )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( SCANNER_ERR_DEVICE_NOT_FOUND ) } ;
show_setting_ = true ;
bUiOnly_ = bUiOnly ;
// display user UI ... (setting UI, can we show my own main window here ?)
return scanner_ - > ui_show_setting ( ( HWND ) data . parent ( ) . raw ( ) , ! bUiOnly , m_bIndicator ) ? success ( ) : seqError ( ) ;
}
2023-09-22 08:26:22 +00:00
void huagao_ds : : init_support_caps ( int err )
2023-07-10 07:28:45 +00:00
{
2023-09-21 03:23:38 +00:00
std : : vector < uint32_t > ids ;
scanner_ - > get_fixed_ids ( got_fixed_id , & ids ) ;
std : : sort ( ids . begin ( ) , ids . end ( ) ) ;
2023-07-10 07:28:45 +00:00
m_query . clear ( ) ;
m_caps . clear ( ) ;
org_func_ . clear ( ) ;
m_query [ CapType : : SupportedCaps ] = msgSupportGetAll ;
m_caps [ CapType : : SupportedCaps ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
if ( ( msg = = Msg : : Get ) | | ( Msg : : GetCurrent = = msg ) | | ( Msg : : GetDefault = = msg ) ) {
data = Capability : : createArray < CapType : : SupportedCaps > ( m_caps . size ( ) ) ;
auto arr = data . array < CapType : : SupportedCaps > ( ) ;
std : : vector < unsigned int > all ;
for ( const auto & v : m_caps )
all . push_back ( ( int ) v . first ) ;
std : : sort ( all . begin ( ) , all . end ( ) ) ;
UInt32 i = 0 ;
for ( const auto & kv : all ) {
arr [ i ] = ( CapType ) kv ;
i + + ;
}
return success ( ) ;
}
else
return capBadOperation ( ) ;
} ;
2023-09-22 08:26:22 +00:00
if ( err = = 0 )
{
m_query [ CapType : : IExtImageInfo ] = msgSupportGetAll ;
m_caps [ CapType : : IExtImageInfo ] = std : : bind ( enmGet < Bool > , _2 , _3 , Bool ( true ) ) ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : ISupportedExtImageInfo ] = msgSupportGetAll ;
m_caps [ CapType : : ISupportedExtImageInfo ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) {
data = Capability : : createArray < CapType : : ISupportedExtImageInfo > ( { InfoId : : BarCodeCount , InfoId : : BarCodeText , InfoId : : BarCodeType , InfoId : : BarCodeTextLength } ) ;
return success ( ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : XferCount ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : XferCount ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
std : : vector < std : : string > all ;
bool dup = true ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
GET_SANE_OPT ( std : : string , scanner_ , PAGE , NULL , & all ) ;
dup = s2t : : page_is_duplex ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
if ( msg = = Msg : : Set ) {
auto item = data . currentItem < Int16 > ( ) ;
if ( item > 65535 | | item < - 1 | | item = = 0 ) {
return badValue ( ) ;
}
int ret = SCANNER_ERR_OK ;
int count = count_ = item ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( dup & & count > = 2 )
{
count + + ;
count / = 2 ;
}
SET_SANE_OPT ( ret , scanner_ , SCAN_COUNT , & count ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
std : : vector < int > count ;
Int16 tmp_count = 0 ;
GET_SANE_OPT ( int , scanner_ , SCAN_COUNT , NULL , & count ) ;
tmp_count = count [ sane_opts : : RANGE_POS_CURRENT ] ;
if ( dup & & tmp_count > 0 & & tmp_count < 65535 )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
tmp_count * = 2 ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
return oneValGetSet < Int16 > ( msg , data , tmp_count , ( Int16 ) count [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
2023-07-10 07:28:45 +00:00
} ;
2023-09-22 08:26:22 +00:00
m_bIndicator = scanner_ - > ui_is_ok ( ) ;
if ( m_bIndicator )
{
m_query [ CapType : : UiControllable ] = msgSupportGetAll ;
m_caps [ CapType : : UiControllable ] = std : : bind ( oneValGet < Bool > , _2 , _3 , Bool ( true ) ) ;
m_query [ CapType : : Indicators ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : Indicators ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto show = data . currentItem < CapType : : Indicators > ( ) ;
m_bIndicator = show ;
utils : : log_info ( m_bIndicator ? " Set show indicator: true \r \n " : " Set show indicator: false \r \n " , 0 ) ;
return success ( ) ;
}
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( ! data . operator bool ( ) )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
data = Capability : : createEnumeration < CapType : : Indicators > ( { FALSE , TRUE } , m_bIndicator ? 1 : 0 , 1 ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
else
data = Capability : : createOneValue < CapType : : Indicators > ( m_bIndicator ) ;
2023-07-10 07:28:45 +00:00
return success ( ) ;
2023-09-22 08:26:22 +00:00
} ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
m_query [ CapType : : DeviceOnline ] = msgSupportGetAll ;
m_caps [ CapType : : DeviceOnline ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : DeviceOnline > ( ( Twpp : : Bool ) scanner_ - > is_online ( ) ) ;
return success ( ) ;
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
}
} ;
m_query [ CapType : : ICompression ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : ICompression ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : ICompression > ( ) ;
if ( Compression : : None = = mech | | mech = = Compression : : Group4 ) {
m_compression = mech ;
scanner_ - > twain_set_compression ( ( SANE_CompressionType ) m_compression ) ;
{
utils : : to_log ( LOG_LEVEL_ALL , " set CapType::ICompression = %s \r \n " , Compression : : None = = mech ? " None " : " Group4 " ) ;
}
return success ( ) ;
}
else
return badValue ( ) ;
}
return CapSupGetAllReset < Compression , Compression , CapType : : ICompression > ( msg , data , { Compression : : None , Compression : : Group4 } , m_compression , Compression : : None , m_compression = = Compression : : None ? 0 : 1 , 0 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( scanner_ - > get_option_info ( SANE_OPT_ID_LANGUAGE , NULL , NULL , NULL , NULL ) )
{
m_query [ CapType : : Language ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : Language ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
std : : vector < int > all ;
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , LANGUAGE , NULL , & sall ) ;
for ( auto & v : sall )
all . push_back ( s2t : : language_to_twain ( v . c_str ( ) ) ) ;
sall . clear ( ) ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
int mech = ( int ) data . currentItem < CapType : : Language > ( ) ;
if ( Msg : : Reset = = msg )
mech = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
std : : string val ( s2t : : language_from_twain ( mech ) ) ;
int ret = 0 ;
SET_SANE_OPT ( ret , scanner_ , LANGUAGE , & val [ 0 ] ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
UInt16 cur = all [ sane_opts : : RANGE_POS_CURRENT ] , init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
int ni = 0 , ii = 0 ;
std : : list < UInt16 > alll ;
for ( int i = 0 ; i < all . size ( ) - sane_opts : : RANGE_POS_ENUM_BEGIN ; + + i )
{
if ( all [ i + sane_opts : : RANGE_POS_ENUM_BEGIN ] = = cur )
ni = i ;
else if ( all [ i + sane_opts : : RANGE_POS_ENUM_BEGIN ] = = init )
ii = i ;
alll . push_back ( all [ i + sane_opts : : RANGE_POS_ENUM_BEGIN ] ) ;
}
return cap_get_enum_values < UInt16 , CapType : : Language > ( msg , data , alll , cur , init , ni , ii ) ;
} ;
}
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IUnits ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IUnits ] = std : : bind ( enmGetSetConst < Unit > , _2 , _3 , Unit : : Inches ) ;
m_query [ CapType : : IBitDepth ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IBitDepth ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
std : : vector < int > all ;
std : : vector < std : : string > sall ;
int val = 0 ;
GET_SANE_OPT ( std : : string , scanner_ , COLOR_MODE , NULL , & sall ) ;
2023-09-21 03:23:38 +00:00
for ( auto & v : sall )
2023-09-22 08:26:22 +00:00
all . push_back ( s2t : : bits_from_sane ( v . c_str ( ) ) ) ;
2023-09-21 03:23:38 +00:00
sall . clear ( ) ;
2023-07-10 07:28:45 +00:00
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
2023-09-22 08:26:22 +00:00
if ( no_bitdepth_ )
2023-07-10 07:28:45 +00:00
return success ( ) ;
2023-09-22 08:26:22 +00:00
int ret = SCANNER_ERR_INVALID_PARAMETER ;
val = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Set = = msg )
{
auto mech = data . currentItem < CapType : : IBitDepth > ( ) ;
if ( mech = = 1 )
val = COLOR_BW ;
else if ( mech = = 8 )
val = COLOR_GRAY ;
else if ( mech = = 24 )
val = COLOR_RGB ;
else
{
val = COLOR_RGB ; // mech;
utils : : to_log ( LOG_LEVEL_WARNING , " Set bit-depth to %d is out of range, we set to RGB \r \n " , ( int ) mech ) ;
}
}
2023-07-24 08:55:14 +00:00
{
2023-09-22 08:26:22 +00:00
char info [ 128 ] = { 0 } ;
sprintf ( info , " set CapType::IBitDepth = %d \r \n " , val ) ;
utils : : log_info ( info , 0 ) ;
2023-07-24 08:55:14 +00:00
}
2023-09-22 08:26:22 +00:00
std : : string sv ( s2t : : bits_to_sane ( val ) ) ;
SET_SANE_OPT ( ret , scanner_ , COLOR_MODE , & sv [ 0 ] ) ;
if ( Msg : : Reset = = msg )
{
UINT16 v = val ;
data = Capability : : createOneValue < UINT16 > ( CapType : : IBitDepth , v ) ;
}
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
UINT16 Now = bit_depth_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] ) , Init = bit_depth_from_sane ( all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
std : : list < UINT16 > vals ;
UInt32 ni = distance < int > ( all , all [ sane_opts : : RANGE_POS_CURRENT ] ) ,
ii = distance < int > ( all , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
vals . push_back ( bit_depth_from_sane ( all [ i ] ) ) ;
return cap_get_enum_values < UINT16 , CapType : : IBitDepth > ( msg , data , vals , Now , Init , ni , ii ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IBitOrder ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IBitOrder ] = std : : bind ( oneValGetSetConst < BitOrder > , _2 , _3 , BitOrder : : MsbFirst ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IPlanarChunky ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IPlanarChunky ] = std : : bind ( enmGetSetConst < PlanarChunky > , _2 , _3 , PlanarChunky : : Chunky ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IXResolution ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IXResolution ] = /*m_caps[CapTypeEx::CAP_EX_SANE_resolution];*/ [ this ] ( Twpp : : CapType type , Twpp : : Msg msg , Capability & data ) {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
std : : vector < int > values ;
value_limit limit = VAL_LIMIT_RANGE ;
int init = 0 , now = 0 ;
GET_SANE_OPT ( int , scanner_ , RESOLUTION , NULL , & values ) ;
init = values [ sane_opts : : RANGE_POS_DEFAULT ] ;
now = values [ sane_opts : : RANGE_POS_CURRENT ] ;
switch ( msg ) {
case Msg : : Get :
if ( limit = = VAL_LIMIT_RANGE )
{
data = Capability : : createRange < CapType : : IXResolution > ( Fix32 ( ( float ) values [ sane_opts : : RANGE_POS_LOWER ] )
, Fix32 ( ( float ) values [ sane_opts : : RANGE_POS_UPPER ] )
, Fix32 ( ( float ) values [ sane_opts : : RANGE_POS_STEP ] )
, Fix32 ( ( float ) values [ sane_opts : : RANGE_POS_CURRENT ] )
, Fix32 ( ( float ) values [ sane_opts : : RANGE_POS_DEFAULT ] ) ) ;
return success ( ) ;
}
else if ( limit = = VAL_LIMIT_ENUM )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
std : : list < Fix32 > vals ;
Fix32 Now , Init ;
UInt32 ni , ii ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < values . size ( ) ; + + i )
{
Fix32 f ;
float vf = ( float ) values [ i ] ;
copy_type ( f , vf ) ;
vals . push_back ( f ) ;
}
float nowf = ( float ) now , initf = ( float ) init ;
copy_type ( Now , nowf ) ;
copy_type ( Init , initf ) ;
ni = std : : distance ( vals . begin ( ) , std : : find ( vals . begin ( ) , vals . end ( ) , Now ) ) ;
ii = std : : distance ( vals . begin ( ) , std : : find ( vals . begin ( ) , vals . end ( ) , Init ) ) ;
return cap_get_enum_values < Fix32 , CapType : : IXResolution > ( msg , data , vals , Now , Init , ni , ii ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
case Msg : : GetCurrent :
data = Capability : : createOneValue < CapType : : IXResolution > ( Fix32 ( ( float ) now ) ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : IXResolution > ( Fix32 ( ( float ) init ) ) ;
return success ( ) ;
case Msg : : Reset :
data = Capability : : createOneValue < CapType : : IXResolution > ( Fix32 ( ( float ) init ) ) ;
case Msg : : Set : {
auto mech = data . currentItem < CapType : : IXResolution > ( ) ;
int ret = SCANNER_ERR_OK ;
float resl = ( float ) mech ;
int resli = ( int ) resl ;
SET_SANE_OPT ( ret , scanner_ , RESOLUTION , & resli ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
default :
return capBadOperation ( ) ;
}
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IYResolution ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IYResolution ] = /*m_caps[CapType::IXResolution];*/ [ this ] ( Twpp : : CapType type , Twpp : : Msg msg , Capability & data )
{
Result ret = m_caps [ CapType : : IXResolution ] ( type , msg , data ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( data . type ( ) = = CapType : : IXResolution )
data . dangerous_set_cap ( CapType : : IYResolution ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return ret ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IXNativeResolution ] = msgSupportGetAll ;
m_caps [ CapType : : IXNativeResolution ] = std : : bind ( enmGet < Fix32 > , _2 , _3 , Fix32 ( 200.0 ) ) ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IYNativeResolution ] = msgSupportGetAll ;
m_caps [ CapType : : IYNativeResolution ] = m_caps [ CapType : : IXNativeResolution ] ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : ISupportedSizes ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : ISupportedSizes ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int now = 0 ,
init = 0 ;
std : : vector < int > all ;
std : : vector < std : : string > sall ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
GET_SANE_OPT ( std : : string , scanner_ , PAPER , NULL , & sall ) ;
for ( auto & v : sall )
{
int e = s2t : : paper_size_from_sane ( v . c_str ( ) ) ;
if ( all . size ( ) < 2 | | std : : find ( all . begin ( ) + 2 , all . end ( ) , e ) = = all . end ( ) )
all . push_back ( e ) ;
}
sall . clear ( ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
now = all [ sane_opts : : RANGE_POS_CURRENT ] ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
if ( msg = = Msg : : Set )
init = ( int ) data . currentItem < CapType : : ISupportedSizes > ( ) ;
else
data = Capability : : createOneValue < CapType : : ISupportedSizes > ( ( Twpp : : PaperSize ) init ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
std : : string val ( s2t : : paper_size_to_sane ( init ) ) ;
SET_SANE_OPT ( now , scanner_ , PAPER , & val [ 0 ] ) ;
return now = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
std : : list < Twpp : : PaperSize > vals ;
Twpp : : PaperSize Now = ( PaperSize ) now ,
Init = ( PaperSize ) init ;
UInt32 ni = distance < int > ( all , now ) ,
ii = distance < int > ( all , init ) ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
vals . push_back ( ( PaperSize ) all [ i ] ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return cap_get_enum_values < Twpp : : PaperSize , CapType : : ISupportedSizes > ( msg , data , vals , Now , Init , ni , ii ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IPhysicalWidth ] = msgSupportGetAll ;
m_caps [ CapType : : IPhysicalWidth ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
{
float init = 10.0f ;
int cur = dpi_ ;
SANE_Parameters param ;
memset ( & param , 0 , sizeof ( param ) ) ;
if ( scanner_ . get ( ) & & scanner_ - > get_first_image_header ( & param , NULL , & cur ) )
init = param . pixels_per_line * 1.0f / cur ;
data = Capability : : createOneValue < Fix32 > ( data . type ( ) , Fix32 ( init ) ) ;
2023-07-10 07:28:45 +00:00
return success ( ) ;
}
2023-09-22 08:26:22 +00:00
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
} ;
m_query [ CapType : : IPhysicalHeight ] = msgSupportGetAll ;
m_caps [ CapType : : IPhysicalHeight ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) CapType : : IPhysicalHeight , ( int ) msg ) ;
switch ( msg ) {
case Msg : : Get :
case Msg : : GetCurrent :
case Msg : : GetDefault :
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
float init = 10.0f ;
int cur = dpi_ ;
SANE_Parameters param ;
memset ( & param , 0 , sizeof ( param ) ) ;
if ( scanner_ . get ( ) & & scanner_ - > get_first_image_header ( & param , NULL , & cur ) )
init = param . lines * 1.0f / cur ;
data = Capability : : createOneValue < Fix32 > ( data . type ( ) , Fix32 ( init ) ) ;
return success ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
default :
return { ReturnCode : : Failure , ConditionCode : : CapBadOperation } ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IPixelFlavor ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IPixelFlavor ] = std : : bind ( enmGetSetConst < PixelFlavor > , _2 , _3 , PixelFlavor : : Chocolate ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IXferMech ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IXferMech ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IXferMech > ( ) ;
if ( mech = = XferMech : : Native | | mech = = XferMech : : Memory | | mech = = XferMech : : File ) {
m_capXferMech = mech ;
scanner_ - > twain_set_transfer ( ( twain_xfer ) m_capXferMech ) ;
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
char * des [ ] = { " Native " , " File " , " Memory " , " Unknown " , " MemFile " } ;
utils : : to_log ( LOG_LEVEL_DEBUG , " set CapType::IXferMech = %s \r \n " , des [ ( int ) m_capXferMech ] ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
return success ( ) ;
}
else {
return badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
}
2023-09-22 08:26:22 +00:00
Result r = CapSupGetAllReset < XferMech , XferMech , CapType : : IXferMech > ( msg , data , { XferMech : : Native , XferMech : : File , XferMech : : Memory } , m_capXferMech , XferMech : : Native , ( int ) m_capXferMech , 0 ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return r ;
} ;
m_query [ CapType : : IPixelType ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IPixelType ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( ! scanner_ . get ( ) )
return seqError ( ) ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
std : : vector < int > values ;
std : : vector < std : : string > svalues ;
int init = 0 , now = 0 ;
GET_SANE_OPT ( std : : string , scanner_ , COLOR_MODE , NULL , & svalues ) ;
for ( auto & v : svalues )
values . push_back ( s2t : : pixel_type_from_sane ( v . c_str ( ) ) ) ;
svalues . clear ( ) ;
now = values [ sane_opts : : RANGE_POS_CURRENT ] ;
init = values [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Reset = = msg | | Msg : : Set = = msg )
2023-09-21 03:23:38 +00:00
{
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg )
init = ( int ) data . currentItem < CapType : : IPixelType > ( ) ;
{
char * des [ ] = { " BlackWhite " , " Gray " , " Rgb " } ;
if ( ( int ) init < _countof ( des ) )
utils : : to_log ( LOG_LEVEL_DEBUG , " set CapType::IPixelType = %s \r \n " , des [ ( int ) init ] ) ;
else
utils : : to_log ( LOG_LEVEL_DEBUG , " set CapType::IPixelType = 0x%x \r \n " , ( int ) init ) ;
}
int ret = SCANNER_ERR_OK ;
std : : string sv ( s2t : : pixel_type_to_sane ( init ) ) ;
SET_SANE_OPT ( ret , scanner_ , COLOR_MODE , & sv [ 0 ] ) ;
data = Capability : : createOneValue < CapType : : IPixelType > ( ( Twpp : : PixelType ) init ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-09-21 03:23:38 +00:00
}
2023-09-22 08:26:22 +00:00
switch ( msg ) {
case Msg : : Get :
if ( 1 )
{
std : : list < Twpp : : PixelType > vals ;
UInt32 ni = distance < int > ( values , now ) , ii = distance < int > ( values , init ) ;
Twpp : : PixelType Init = ( Twpp : : PixelType ) init , Now = ( Twpp : : PixelType ) now ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < values . size ( ) ; + + i )
vals . push_back ( ( Twpp : : PixelType ) values [ i ] ) ;
return cap_get_enum_values < Twpp : : PixelType , CapType : : IPixelType > ( msg , data , vals , Now , Init , ni , ii ) ;
}
case Msg : : GetCurrent :
data = Capability : : createOneValue < CapType : : IPixelType > ( ( Twpp : : PixelType ) now ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : IPixelType > ( ( Twpp : : PixelType ) init ) ;
return success ( ) ;
2023-09-21 03:23:38 +00:00
}
2023-09-22 08:26:22 +00:00
return capBadOperation ( ) ;
} ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutomaticColorEnabled ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutomaticColorEnabled ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IAutomaticColorEnabled > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : color_mode_from_auto ( ( bool ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , COLOR_MODE , & val ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return success ( ) ;
}
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , COLOR_MODE , NULL , & all ) ;
int twpt = s2t : : color_mode_is_auto ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ? 1 : 0 ;
return CapSupGetAllReset < int , Bool , CapType : : IAutomaticColorEnabled > ( msg , data , { FALSE , TRUE } , twpt , false , twpt ? 1 : 0 , 0 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutomaticColorNonColorPixelType ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutomaticColorNonColorPixelType ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( msg = = Msg : : Set ) {
int mech = ( int ) data . currentItem < CapType : : IAutomaticColorNonColorPixelType > ( ) ;
{
if ( ( UInt16 ) mech = = 0 | | ( UInt16 ) mech = = 1 ) {
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : color_mode_from_auto ( ( bool ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , COLOR_MODE , & val ) ;
if ( ret = = SCANNER_ERR_OK )
{
automaticcolortype_ = ( UInt16 ) mech ;
return success ( ) ;
}
}
}
return seqError ( ) ;
}
return CapSupGetAllReset < int , PixelType , CapType : : IAutomaticColorNonColorPixelType > ( msg , data , { PixelType : : BlackWhite , PixelType : : Gray } , automaticcolortype_ , PixelType : : Gray , automaticcolortype_ , 1 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IJpegQuality ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IJpegQuality ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
SANE_FinalImgFormat fif ;
fif . img_format = SANE_IMAGE_TYPE_JPG ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IJpegQuality > ( ) ;
if ( ( int ) mech < = 0 | | ( int ) mech > 100 )
return badValue ( ) ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_jpegQuality = ( int ) mech ;
return success ( ) ;
//int ret = SCANNER_ERR_OK;
//fif.detail = (void*)mech;
//SET_SANE_OPT(ret, scanner_, ex_final_format, &fif);
//return ret == SCANNER_ERR_OK ? success() : badValue();
}
//unsigned short q = 80;
//fif.detail = (void*)q;
//GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &fif, NULL, NULL, NULL);
//if(fif.img_format == SANE_IMAGE_TYPE_JPG)
// q = (unsigned short)fif.detail;
//return CapSupGetAllResetEx<unsigned short, UInt16, CapType::IJpegQuality>(msg, data, q, 80);
unsigned short q = m_jpegQuality ;
return CapSupGetAllResetEx < unsigned short , UInt16 , CapType : : IJpegQuality > ( msg , data , q , ( UInt16 ) 80 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IOrientation ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IOrientation ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
int l = 0 ;
char * buf = nullptr ;
std : : string cur ( " " ) ;
bool is_land = false , sp_land = false ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
scanner_ - > get_option_info ( SANE_OPT_ID_PAPER , nullptr , nullptr , & l , nullptr ) ;
buf = new char [ l + 4 ] ;
memset ( buf , 0 , l + 4 ) ;
scanner_ - > get_value ( SANE_OPT_ID_PAPER , buf , & l ) ;
cur = buf ;
delete [ ] buf ;
is_land = s2t : : lateral_from_sane ( cur . c_str ( ) , & sp_land ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IOrientation > ( ) ;
bool lateral = mech = = Orientation : : Landscape ;
int ret = SCANNER_ERR_OK ;
const char * lats [ ] = { " portrait " , " lateral " } ;
if ( lateral = = is_land )
2023-09-21 03:23:38 +00:00
{
2023-09-22 08:26:22 +00:00
// nothing to do ...
utils : : to_log ( LOG_LEVEL_DEBUG , " set paper to '%s' while '%s' is '%s', omit this oper. \r \n " , lats [ lateral ] , cur . c_str ( ) , lats [ lateral ] ) ;
return success ( ) ;
2023-09-21 03:23:38 +00:00
}
2023-09-22 08:26:22 +00:00
if ( lateral & & ! sp_land )
{
utils : : to_log ( LOG_LEVEL_DEBUG , " set paper to 'lateral' but '%s' is not support 'lateral', omit this oper. \r \n " , cur . c_str ( ) ) ;
return badValue ( ) ;
}
cur = s2t : : lateral_to_sane ( cur . c_str ( ) , lateral ) ;
SET_SANE_OPT ( ret , scanner_ , PAPER , & cur [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
int lateral = is_land ? ( int ) Orientation : : Landscape : ( int ) Orientation : : Portrait ;
return CapSupGetAllReset < int , Orientation , CapType : : IOrientation > ( msg , data , { Orientation : : Portrait , Orientation : : Landscape } , lateral , Orientation : : Portrait , lateral = = 0 ? 0 : 1 , 0 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IRotation ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IRotation ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto res = data . currentItem < Fix32 > ( ) ;
2023-10-20 07:21:17 +00:00
double angle = res . toFloat ( ) ;
2023-09-22 08:26:22 +00:00
std : : string val ( s2t : : rotation_to_sane ( angle ) ) ;
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , TEXT_DIRECTION , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-10-20 07:21:17 +00:00
std : : vector < double > values ;
2023-09-22 08:26:22 +00:00
std : : vector < std : : string > svalues ;
GET_SANE_OPT ( std : : string , scanner_ , TEXT_DIRECTION , NULL , & svalues ) ;
for ( auto & v : svalues )
values . push_back ( s2t : : rotation_from_sane ( v . c_str ( ) ) ) ;
svalues . clear ( ) ;
Fix32 Init = Fix32 ( values [ sane_opts : : RANGE_POS_DEFAULT ] ) , Now = Fix32 ( values [ sane_opts : : RANGE_POS_CURRENT ] ) ;
std : : list < Fix32 > vls ;
2023-10-20 07:21:17 +00:00
UInt32 i = distance < double > ( values , values [ sane_opts : : RANGE_POS_DEFAULT ] ) ,
n = distance < double > ( values , values [ sane_opts : : RANGE_POS_CURRENT ] ) ;
for ( size_t ind = sane_opts : : RANGE_POS_ENUM_BEGIN ; ind < values . size ( ) ; + + ind )
vls . push_back ( Fix32 ( values [ ind ] ) ) ;
2023-09-22 08:26:22 +00:00
return cap_get_enum_values < Fix32 , CapType : : IRotation > ( msg , data , vls , Now , Init , n , i ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : EnableDsUiOnly ] = msgSupportGetAll ;
m_caps [ CapType : : EnableDsUiOnly ] = std : : bind ( enmGet < Bool > , _2 , _3 , Bool ( true ) ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : PaperDetectable ] = msgSupportGetAll ;
m_caps [ CapType : : PaperDetectable ] = std : : bind ( oneValGet < Bool > , _2 , _3 , Bool ( true ) ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : FeederEnabled ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : FeederEnabled ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : FeederEnabled > ( ) ;
m_bFeederEnabled = mech ;
return success ( ) ;
}
return CapSupGetAllReset < bool , Bool , CapType : : FeederEnabled > ( msg , data , m_bFeederEnabled , Bool ( true ) ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : Duplex ] = msgSupportGetAll ;
m_caps [ CapType : : Duplex ] = std : : bind ( oneValGet < Duplex > , _2 , _3 , Duplex : : OnePass ) ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : DuplexEnabled ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : DuplexEnabled ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int count = 0 , l = sizeof ( count ) ;
scanner_ - > get_value ( SANE_OPT_ID_SCAN_COUNT , & count , & l ) ;
if ( Msg : : Set = = msg ) {
bool mech = data . currentItem < CapType : : DuplexEnabled > ( ) ;
std : : string val ( s2t : : page_from_duplex ( mech ) ) ;
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , PAGE , & val [ 0 ] ) ;
utils : : log_info ( mech ? " Set1 Duplex is: true \r \n " : " Set1 Duplex is: false \r \n " , 1 ) ;
if ( ret = = SCANNER_ERR_OK )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
if ( mech & & count > = 2 )
{
count / = 2 ;
SET_SANE_OPT ( ret , scanner_ , SCAN_COUNT , & count ) ;
}
else if ( ! mech & & count_ > = 2 )
SET_SANE_OPT ( ret , scanner_ , SCAN_COUNT , & count ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-09-21 03:23:38 +00:00
}
2023-09-22 08:26:22 +00:00
BYTE dup = 1 ;
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , PAGE , NULL , & all ) ;
dup = s2t : : page_is_duplex ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
utils : : log_info ( dup ? " Get Duplex is: true \r \n " : " Get Duplex is: false \r \n " , 1 ) ;
2023-07-10 07:28:45 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
if ( dup & & count > = 2 )
{
count / = 2 ;
SET_SANE_OPT ( ret , scanner_ , SCAN_COUNT , & count ) ;
}
else if ( ! dup & & count > = 2 )
SET_SANE_OPT ( ret , scanner_ , SCAN_COUNT , & count )
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return CapSupGetAllReset < BYTE , Bool , CapType : : DuplexEnabled > ( msg , data , dup , Bool ( true ) ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : AutoFeed ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : AutoFeed ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : AutoFeed > ( ) ;
m_bAutoFeed = mech ;
return success ( ) ;
}
return CapSupGetAllReset < bool , Bool , CapType : : AutoFeed > ( msg , data , { false , true } , m_bAutoFeed , true , m_bAutoFeed ? 1 : 0 , 1 ) ;
2023-09-21 03:23:38 +00:00
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IImageFileFormat ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IImageFileFormat ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
SANE_FinalImgFormat now , init ;
2023-07-10 07:28:45 +00:00
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg )
{
auto fmt = data . currentItem < ImageFileFormat > ( ) ;
if ( fmt ! = Twpp : : ImageFileFormat : : Bmp & &
fmt ! = Twpp : : ImageFileFormat : : Jfif & &
fmt ! = Twpp : : ImageFileFormat : : Tiff )
return badValue ( ) ;
init . img_format = ( SANE_ImageType ) fmt ;
{
if ( fmt = = Twpp : : ImageFileFormat : : Bmp )
utils : : log_info ( " set CapType::IImageFileFormat = Bmp \r \n " , 1 ) ;
else if ( fmt = = Twpp : : ImageFileFormat : : Jfif )
utils : : log_info ( " set CapType::IImageFileFormat = Jfif \r \n " , 1 ) ;
else if ( fmt = = Twpp : : ImageFileFormat : : Tiff )
utils : : log_info ( " set CapType::IImageFileFormat = Tiff \r \n " , 1 ) ;
}
}
else
data = Capability : : createOneValue < CapType : : IImageFileFormat > ( ( Twpp : : ImageFileFormat ) init . img_format ) ;
m_fileXfer . setFormat ( ( Twpp : : ImageFileFormat ) init . img_format ) ;
return success ( ) ;
}
ImageFileFormat Now = m_fileXfer . format ( ) , Init = Twpp : : ImageFileFormat : : Bmp ;
std : : list < ImageFileFormat > vals ;
UInt32 i = 0 , // distance<SANE_FinalImgFormat>(all, init),
n = 0 ; // distance<SANE_FinalImgFormat>(all, now);
vals . push_back ( Twpp : : ImageFileFormat : : Bmp ) ;
vals . push_back ( Twpp : : ImageFileFormat : : Jfif ) ;
vals . push_back ( Twpp : : ImageFileFormat : : Tiff ) ;
int ind = 0 ;
for ( auto & v : vals )
{
if ( v = = Now )
{
n = ind ;
break ;
}
ind + + ;
2023-07-10 07:28:45 +00:00
}
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
return cap_get_enum_values < ImageFileFormat , CapType : : IImageFileFormat > ( msg , data , vals , Now , Init , n , i ) ;
2023-07-10 07:28:45 +00:00
} ;
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutomaticDeskew ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutomaticDeskew ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto atuodsw = data . currentItem < CapType : : IAutomaticDeskew > ( ) ;
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , ANTI_SKEW , ( bool * ) & atuodsw ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : seqError ( ) ;
}
BYTE ato = 1 ;
std : : vector < bool > all ;
GET_SANE_OPT ( bool , scanner_ , ANTI_SKEW , NULL , & all ) ;
ato = all [ sane_opts : : RANGE_POS_CURRENT ] ;
return CapSupGetAllReset < BYTE , bool , CapType : : IAutomaticDeskew > ( msg , data , ato , true ) ;
} ;
m_query [ CapType : : IAutomaticRotate ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutomaticRotate ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IAutomaticRotate > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : auto_rotation_to_sane ( ( bool ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , TEXT_DIRECTION , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
float direction = .0f ;
BYTE am = 0 ;
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , TEXT_DIRECTION , NULL , & all ) ;
am = s2t : : auto_rotation_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
return CapSupGetAllReset < BYTE , bool , CapType : : IAutomaticRotate > ( msg , data , am , false ) ;
} ;
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_DEVICE_SERIAL_NO ) ! = ids . end ( ) )
{
m_query [ CapType : : SerialNumber ] = msgSupportGetAll ;
m_caps [ CapType : : SerialNumber ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
Str255 str ;
int l = 255 ;
scanner_ - > get_value ( SANE_OPT_ID_DEVICE_SERIAL_NO , str . data ( ) , & l ) ;
return CapSupGetAll < Str255 , Str255 , CapType : : SerialNumber > ( msg , data , str , str ) ;
} ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_WAIT_TO_SCAN ) ! = ids . end ( ) )
{
m_query [ CapType : : AutoScan ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : AutoScan ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
bool val = false ;
if ( Msg : : Set = = msg )
val = ( bool ) data . currentItem < CapType : : AutoScan > ( ) ;
int ret = SANE_STATUS_GOOD ;
m_autoscan = val ;
SET_SANE_OPT ( ret , scanner_ , WAIT_TO_SCAN , & val ) ;
return ret = = SANE_STATUS_GOOD ? success ( ) : badValue ( ) ;
}
std : : vector < bool > all ;
GET_SANE_OPT ( bool , scanner_ , WAIT_TO_SCAN , NULL , & all ) ;
m_autoscan = ( bool ) all [ sane_opts : : RANGE_POS_CURRENT ] ;
return CapSupGetAllReset < Bool , Bool , CapType : : AutoScan > ( msg , data , m_autoscan , ( bool ) all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
} ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutoSize ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutoSize ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
CapabilityPrintf ( msg , enum2str ( CapType : : IAutoSize ) , msg = = Msg : : Set ? to_string ( ( int ) data . currentItem < CapType : : IAutoSize > ( ) ) : " " ) ;
2023-09-21 03:23:38 +00:00
if ( Msg : : Set = = msg ) {
2023-09-22 08:26:22 +00:00
auto autosize = data . currentItem < CapType : : IAutoSize > ( ) ;
std : : string val ( s2t : : auto_size_to_sane ( autosize = = AutoSize : : Auto ) ) ;
2023-09-21 03:23:38 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
SET_SANE_OPT ( ret , scanner_ , PAPER , & val [ 0 ] ) ;
2023-09-21 03:23:38 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
std : : vector < std : : string > sall ;
2023-09-22 08:26:22 +00:00
GET_SANE_OPT ( std : : string , scanner_ , PAPER , NULL , & sall ) ;
UInt16 size = s2t : : auto_size_from_sane ( sall [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ? ( UInt16 ) AutoSize : : Auto : ( UInt16 ) AutoSize : : None ;
return CapSupGetAllReset < UInt16 , AutoSize , CapType : : IAutoSize > ( msg , data , { AutoSize : : None , AutoSize : : Auto } , size , AutoSize : : None , ( size = = ( UInt16 ) AutoSize : : Auto ) ? 1 : 0 , 0 ) ;
2023-09-21 03:23:38 +00:00
} ;
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutomaticBorderDetection ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutomaticBorderDetection ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
2023-09-22 08:26:22 +00:00
auto autodetectborder = data . currentItem < CapType : : IAutomaticBorderDetection > ( ) ;
2023-10-20 07:21:17 +00:00
std : : string val ( s2t : : auto_size_to_sane ( autodetectborder ) ) ;
2023-09-21 03:23:38 +00:00
int ret = SCANNER_ERR_OK ;
2023-10-20 07:21:17 +00:00
SET_SANE_OPT ( ret , scanner_ , PAPER , ( bool * ) & autodetectborder ) ;
2023-09-21 03:23:38 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-09-22 08:26:22 +00:00
Bool init = false ,
erase = false ;
2023-10-20 07:21:17 +00:00
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , PAPER , NULL , & sall ) ;
init = s2t : : auto_size_from_sane ( sall [ sane_opts : : RANGE_POS_DEFAULT ] . c_str ( ) ) ;
erase = s2t : : auto_size_from_sane ( sall [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
2023-09-22 08:26:22 +00:00
return CapSupGetAllReset < Bool , Bool , CapType : : IAutomaticBorderDetection > ( msg , data , { false , true } , erase , init , erase ? 1 : 0 , 0 ) ;
2023-09-21 03:23:38 +00:00
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_DISCARDBLANK ) = = ids . end ( ) )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutoDiscardBlankPages ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutoDiscardBlankPages ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IAutoDiscardBlankPages > ( ) ;
bool discard = mech = = DiscardBlankPages : : Auto ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : discard_blank_to_sane ( discard ) ) ;
SET_SANE_OPT ( ret , scanner_ , PAGE , & val [ 0 ] ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
std : : vector < bool > all ;
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , PAGE , NULL , & sall ) ;
for ( auto & v : sall )
all . push_back ( s2t : : discard_blank_from_sane ( v . c_str ( ) ) ) ;
DiscardBlankPages autodiscradblank = all [ sane_opts : : RANGE_POS_CURRENT ] ? DiscardBlankPages : : Auto : DiscardBlankPages : : Disabled ;
return CapSupGetAllReset < DiscardBlankPages , DiscardBlankPages , CapType : : IAutoDiscardBlankPages > ( msg , data , autodiscradblank , DiscardBlankPages : : Disabled ) ;
} ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
else
{
m_query [ CapType : : IAutoDiscardBlankPages ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IAutoDiscardBlankPages ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IAutoDiscardBlankPages > ( ) ;
bool discard = mech = = DiscardBlankPages : : Auto ;
int ret = SCANNER_ERR_OK ;
{
SET_SANE_OPT ( ret , scanner_ , DISCARDBLANK , & discard ) ;
}
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
std : : vector < bool > all ;
{
GET_SANE_OPT ( bool , scanner_ , DISCARDBLANK , NULL , & all ) ;
}
DiscardBlankPages autodiscradblank = all [ sane_opts : : RANGE_POS_CURRENT ] ? DiscardBlankPages : : Auto : DiscardBlankPages : : Disabled ;
return CapSupGetAllReset < DiscardBlankPages , DiscardBlankPages , CapType : : IAutoDiscardBlankPages > ( msg , data , autodiscradblank , DiscardBlankPages : : Disabled ) ;
} ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IFilter ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IFilter ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < CapType : : IFilter > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : filter_to_sane ( ( int ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , FILTER , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
int cur = FILTER_NONE , def = FILTER_NONE ;
std : : vector < int > vals ;
std : : vector < std : : string > svals ;
GET_SANE_OPT ( std : : string , scanner_ , FILTER , NULL , & svals ) ;
s2t : : filter_from_sane ( svals , vals , true ) ;
svals . clear ( ) ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
std : : list < Filter > vs ;
Filter now = ( Filter ) ( vals [ sane_opts : : RANGE_POS_CURRENT ] ) ,
init = ( Filter ) ( vals [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
UInt32 curInd = distance < int > ( vals , vals [ sane_opts : : RANGE_POS_CURRENT ] ) ,
defInd = distance < int > ( vals , vals [ sane_opts : : RANGE_POS_DEFAULT ] ) ; ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < vals . size ( ) ; + + i )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
vs . push_back ( ( Filter ) vals [ i ] ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
BYTE f = ( BYTE ) now ;
return CapSupGetAllReset < BYTE , Filter , CapType : : IFilter > ( msg , data , vs , f , init , curInd , defInd ) ;
} ;
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IBrightness ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IBrightness ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
int init = 128 , l = 1 , u = 255 , step = 1 , now = 128 ;
int ret = SCANNER_ERR_OK ;
std : : vector < int > all ;
GET_SANE_OPT ( int , scanner_ , BRIGHTNESS , NULL , & all ) ;
2023-07-10 07:28:45 +00:00
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
now = all [ sane_opts : : RANGE_POS_CURRENT ] ;
l = all [ sane_opts : : RANGE_POS_LOWER ] ;
u = all [ sane_opts : : RANGE_POS_UPPER ] ;
2023-09-22 08:26:22 +00:00
step = all [ sane_opts : : RANGE_POS_STEP ] ;
float sf = trans_range ( ( float ) step , ( float ) l , ( float ) u , - 1000.0f , 1000.0f , true ) ,
nf = trans_range ( ( float ) now , ( float ) l , ( float ) u , - 1000.0f , 1000.0f ) ,
initf = trans_range ( ( float ) init , ( float ) l , ( float ) u , - 1000.0f , 1000.0f ) ;
switch ( msg ) {
case Msg : : Get :
sf = 333.333f ;
data = Capability : : createRange < CapType : : IBrightness > ( Fix32 ( - 1000.0f ) , Fix32 ( 1000.0f ) , Fix32 ( sf ) , Fix32 ( nf ) , Fix32 ( initf ) ) ;
return success ( ) ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < CapType : : IBrightness > ( Fix32 ( nf ) ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : IBrightness > ( Fix32 ( initf ) ) ;
return success ( ) ;
case Msg : : Set : {
auto mech = data . currentItem < CapType : : IBrightness > ( ) ;
if ( mech > 1000.0f | | mech < - 1000.0f )
return badValue ( ) ;
initf = mech . toFloat ( ) ;
}
case Msg : : Reset :
now = ( int ) ( trans_range ( initf , - 1000.0f , 1000.0f , ( float ) l , ( float ) u ) + .5f ) ;
SET_SANE_OPT ( ret , scanner_ , BRIGHTNESS , & now ) ;
if ( Msg : : Reset = = msg )
2023-07-10 07:28:45 +00:00
{
2023-09-22 08:26:22 +00:00
initf = trans_range ( ( float ) now , ( float ) l , ( float ) u , - 1000.0f , 1000.0f , true ) ;
data = Capability : : createOneValue < CapType : : IBrightness > ( Fix32 ( initf ) ) ;
2023-07-10 07:28:45 +00:00
}
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
2023-09-22 08:26:22 +00:00
default :
return capBadOperation ( ) ;
2023-07-10 07:28:45 +00:00
}
} ;
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IContrast ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IContrast ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int init = 4 , l = 1 , u = 7 , step = 1 , now = 4 ;
2023-09-21 03:23:38 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
std : : vector < int > all ;
GET_SANE_OPT ( int , scanner_ , CONTRAST , NULL , & all ) ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
now = all [ sane_opts : : RANGE_POS_CURRENT ] ;
l = all [ sane_opts : : RANGE_POS_LOWER ] ;
u = all [ sane_opts : : RANGE_POS_UPPER ] ;
step = all [ sane_opts : : RANGE_POS_STEP ] ;
float sf = trans_range ( ( float ) step , ( float ) l , ( float ) u , - 1000.0f , 1000.0f , true ) ,
nf = trans_range ( ( float ) now , ( float ) l , ( float ) u , - 1000.0f , 1000.0f ) ,
initf = trans_range ( ( float ) init , ( float ) l , ( float ) u , - 1000.0f , 1000.0f ) ;
switch ( msg ) {
case Msg : : Get :
// sf = 333.333f;
data = Capability : : createRange < CapType : : IContrast > ( Fix32 ( - 1000.0f ) , Fix32 ( 1000.0f ) , Fix32 ( sf ) , Fix32 ( nf ) , Fix32 ( initf ) ) ;
return success ( ) ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < CapType : : IContrast > ( Fix32 ( nf ) ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : IContrast > ( Fix32 ( initf ) ) ;
return success ( ) ;
case Msg : : Set : {
auto mech = data . currentItem < CapType : : IContrast > ( ) ;
if ( mech > 1000.0f | | mech < - 1000.0f )
return badValue ( ) ;
initf = mech . toFloat ( ) ;
}
case Msg : : Reset :
now = ( int ) ( trans_range ( initf , - 1000.0f , 1000.0f , ( float ) l , ( float ) u ) + .5f ) ;
SET_SANE_OPT ( ret , scanner_ , CONTRAST , & now ) ;
if ( Msg : : Reset = = msg )
{
initf = trans_range ( ( float ) now , ( float ) l , ( float ) u , - 1000.0f , 1000.0f , true ) ;
data = Capability : : createOneValue < CapType : : IContrast > ( Fix32 ( initf ) ) ;
}
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
default :
return capBadOperation ( ) ;
}
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IGamma ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : IGamma ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
double init = .0f , l = .0f , u = .0f , step = .0f , now = .0f ;
std : : vector < double > all ;
2023-09-21 03:23:38 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
GET_SANE_OPT ( double , scanner_ , GAMMA , NULL , & all ) ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
now = all [ sane_opts : : RANGE_POS_CURRENT ] ;
l = all [ sane_opts : : RANGE_POS_LOWER ] ;
u = all [ sane_opts : : RANGE_POS_UPPER ] ;
step = all [ sane_opts : : RANGE_POS_STEP ] ;
switch ( msg ) {
case Msg : : Get :
data = Capability : : createRange < CapType : : IGamma > ( Fix32 ( l ) , Fix32 ( u ) , Fix32 ( step ) , Fix32 ( now ) , Fix32 ( init ) ) ;
return success ( ) ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < CapType : : IGamma > ( Fix32 ( now ) ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < CapType : : IGamma > ( Fix32 ( init ) ) ;
return success ( ) ;
case Msg : : Set : {
auto mech = data . currentItem < CapType : : IGamma > ( ) ;
if ( mech > u | | mech < l )
return badValue ( ) ;
init = mech . toFloat ( ) ;
}
case Msg : : Reset :
SET_SANE_OPT ( ret , scanner_ , GAMMA , & init ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
default :
return capBadOperation ( ) ;
}
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : CustomDsData ] = msgSupportGetAll ;
m_caps [ CapType : : CustomDsData ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
Bool init ( true ) ;
return CapSupGetAll < Bool , Bool , CapType : : CustomDsData > ( msg , data , init , init ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : DoubleFeedDetection ] = msgSupportGetAllSetReset ;
m_caps [ CapType : : DoubleFeedDetection ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto val = data . currentItem < CapType : : DoubleFeedDetection > ( ) ;
int ret = SCANNER_ERR_OK ;
bool enable = val = = DoubleFeedDetection : : Ultrasonic ;
if ( double_check_mode_ = = DOUBLE_CHECK_ULTRASONIC )
{
enable = ( bool ) val ;
utils : : to_log ( 1 , " DoubleFeedDetection parameter is boolean for Ultrasonic. set to %s \r \n " , enable ? " TRUE " : " FALSE " ) ;
}
SET_SANE_OPT ( ret , scanner_ , IS_ULTROSONIC_CHECK , & enable ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : seqError ( ) ;
}
DoubleFeedDetection init = DoubleFeedDetection : : Ultrasonic ;
std : : vector < bool > all ;
GET_SANE_OPT ( bool , scanner_ , IS_ULTROSONIC_CHECK , NULL , & all ) ;
if ( double_check_mode_ = = DOUBLE_CHECK_ULTRASONIC )
{
Bool ni ( all [ sane_opts : : RANGE_POS_CURRENT ] ) ,
ii ( all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
data = Capability : : createEnumeration < Bool > ( CapType : : DoubleFeedDetection , { FALSE , TRUE } , ni , ii ) ;
return success ( ) ;
}
else
{
BYTE ato = ! all [ sane_opts : : RANGE_POS_CURRENT ] ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ? DoubleFeedDetection : : Ultrasonic : DoubleFeedDetection : : ByLength ;
return CapSupGetAllReset < BYTE , DoubleFeedDetection , CapType : : DoubleFeedDetection > ( msg , data , ato , init ) ;
}
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : IAutomaticCropUsesFrame ] = msgSupportGetAll ;
m_caps [ CapType : : IAutomaticCropUsesFrame ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , PAPER , NULL , & all ) ;
BYTE crop = s2t : : auto_size_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ; // FIXED ME !!! whether should be !AutoSize
return CapSupGetAll < BYTE , bool , CapType : : IAutomaticCropUsesFrame > ( msg , data , crop , false ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType : : FeederLoaded ] = msgSupportGetAll ;
m_caps [ CapType : : FeederLoaded ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
Bool paperon = scanner_ - > is_paper_on ( ) ;
return CapSupGetAll < Bool , Bool , CapType : : FeederLoaded > ( msg , data , paperon , paperon ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
m_query [ ( CapType ) CAP_TYPE_EX_DISCARD_BLANK_RECEIPT ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CAP_TYPE_EX_DISCARD_BLANK_RECEIPT ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto mech = data . currentItem < DiscardBlankPages > ( ) ;
bool discard = mech = = DiscardBlankPages : : Auto ;
std : : string val ( s2t : : discard_blank_receipt_to_sane ( discard ) ) ;
2023-07-10 07:28:45 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
SET_SANE_OPT ( ret , scanner_ , PAGE , & val [ 0 ] ) ;
2023-07-10 07:28:45 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-09-22 08:26:22 +00:00
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , PAGE , NULL , & all ) ;
DiscardBlankPages autodiscradblank = s2t : : discard_blank_receipt_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ? DiscardBlankPages : : Auto : DiscardBlankPages : : Disabled ;
return CapSupGetAllResetEx < DiscardBlankPages , DiscardBlankPages , ( CapType ) CapTypeEx : : CAP_TYPE_EX_DISCARD_BLANK_RECEIPT > ( msg , data , autodiscradblank , DiscardBlankPages : : Disabled ) ;
// return success();
} ;
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_FILL_HOLE_RATIO ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_FILL_HOLE_RATIO ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
double init = .0f , l = .0f , u = .0f , step = .0f , now = .0f ;
std : : vector < double > all ;
int ret = SCANNER_ERR_OK ;
GET_SANE_OPT ( double , scanner_ , SEARCH_HOLE_RANGE_L , NULL , & all ) ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] * 100.0f ;
now = all [ sane_opts : : RANGE_POS_CURRENT ] * 100.0f ;
l = all [ sane_opts : : RANGE_POS_LOWER ] * 100.0f ;
u = all [ sane_opts : : RANGE_POS_UPPER ] * 100.0f ;
step = all [ sane_opts : : RANGE_POS_STEP ] * 100.0f ;
switch ( msg ) {
case Msg : : Get :
data = Capability : : createRange < UInt32 > ( ( CapType ) CapTypeEx : : CAP_TYPE_EX_FILL_HOLE_RATIO , UInt32 ( l ) , UInt32 ( u ) , UInt32 ( step ) , UInt32 ( now ) , UInt32 ( init ) ) ;
return success ( ) ;
case Msg : : GetCurrent :
data = Capability : : createOneValue < UInt32 > ( ( CapType ) CapTypeEx : : CAP_TYPE_EX_FILL_HOLE_RATIO , UInt32 ( now ) ) ;
return success ( ) ;
case Msg : : GetDefault :
data = Capability : : createOneValue < UInt32 > ( ( CapType ) CapTypeEx : : CAP_TYPE_EX_FILL_HOLE_RATIO , UInt32 ( init ) ) ;
return success ( ) ;
case Msg : : Set : {
auto mech = data . currentItem < UInt32 > ( ) ;
if ( mech > u | | mech < l )
return badValue ( ) ;
init = ( float ) mech ;
}
case Msg : : Reset :
init / = 100.0f ;
SET_SANE_OPT ( ret , scanner_ , SEARCH_HOLE_RANGE_L , & init ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
default :
return capBadOperation ( ) ;
2023-07-10 07:28:45 +00:00
}
} ;
2023-09-22 08:26:22 +00:00
m_query [ CapType ( CapTypeEx : : CAP_TYPE_EX_FOLD ) ] = msgSupportGetAllSetReset ;
m_caps [ CapType ( CapTypeEx : : CAP_TYPE_EX_FOLD ) ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-09-22 08:26:22 +00:00
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
bool fold = false ;
if ( msg = = Msg : : Set )
fold = ( bool ) data . currentItem < Int32 > ( ) ;
std : : string val ( s2t : : fold_to_sane ( fold ) ) ;
2023-07-10 07:28:45 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
SET_SANE_OPT ( ret , scanner_ , PAGE , & val [ 0 ] ) ;
2023-07-10 07:28:45 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-09-21 03:23:38 +00:00
std : : vector < std : : string > all ;
2023-09-22 08:26:22 +00:00
GET_SANE_OPT ( std : : string , scanner_ , PAGE , NULL , & all ) ;
BYTE fold = s2t : : fold_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
return CapSupGetAllResetEx < BYTE , Int32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_FOLD > ( msg , data , fold , 0 ) ;
2023-07-10 07:28:45 +00:00
} ;
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_DOG_EAR_SIZE ) = = ids . end ( ) )
{
m_query [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_DOGEAR_DIST ) ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_DOGEAR_DIST ) ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int now = 10 , init = 10 , l = 0 , u = 100 , s = 10 ;
std : : vector < int > all ;
GET_SANE_OPT ( int , scanner_ , DOG_EAR_SIZE , NULL , & all ) ;
init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
now = all [ sane_opts : : RANGE_POS_CURRENT ] ;
l = all [ sane_opts : : RANGE_POS_LOWER ] ;
u = all [ sane_opts : : RANGE_POS_UPPER ] ;
s = all [ sane_opts : : RANGE_POS_STEP ] ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
if ( Msg : : Set = = msg )
{
auto mech = data . currentItem < UInt32 > ( ) ;
if ( mech < 10 | | mech > 300 )
return badValue ( ) ;
init = ( int ) ( trans_range ( ( float ) mech , 10.0f , 300.0f , ( float ) l , ( float ) u ) + .5f ) ;
}
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , DOG_EAR_SIZE , & init ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
UInt32 Now = UInt32 ( trans_range ( ( float ) now , ( float ) l , ( float ) u , 10.0f , 300.0f ) + .5f ) ,
Init = UInt32 ( trans_range ( ( float ) init , ( float ) l , ( float ) u , 10.0f , 300.0f ) + .5f ) ;
return CapSupGetAllResetEx < UInt32 , UInt32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_DOGEAR_DIST > ( msg , data , Now , Init ) ;
} ;
}
m_query [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_CROP_MODEL ) ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_CROP_MODEL ) ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , PAPER , NULL , & all ) ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg )
{
bool def = s2t : : auto_crop_from_sane ( all [ sane_opts : : RANGE_POS_DEFAULT ] . c_str ( ) ) ;
if ( Msg : : Set = = msg )
def = data . currentItem < BYTE > ( ) = = 1 ;
std : : string val ( s2t : : auto_crop_to_sane ( def ) ) ;
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , PAPER , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
BYTE crop = s2t : : auto_crop_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ,
init = s2t : : auto_crop_from_sane ( all [ sane_opts : : RANGE_POS_DEFAULT ] . c_str ( ) ) ;
return CapSupGetAll < BYTE , bool , CapType : : IAutomaticCropUsesFrame > ( msg , data , crop , init ) ;
} ;
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_MULTI_OUT_TYPE ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_MULTI_OUT_TYPE ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-09-21 03:23:38 +00:00
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
int cur = MULTI_OUT_NONE , def = MULTI_OUT_NONE ;
std : : vector < int > all ;
2023-09-22 08:26:22 +00:00
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , MULTI_OUT_TYPE , NULL , & sall ) ;
2023-09-21 03:23:38 +00:00
for ( auto & v : sall )
2023-09-22 08:26:22 +00:00
all . push_back ( s2t : : multi_out_from_sane ( v . c_str ( ) ) ) ;
2023-09-21 03:23:38 +00:00
sall . clear ( ) ;
2023-07-10 07:28:45 +00:00
cur = all [ sane_opts : : RANGE_POS_CURRENT ] ;
def = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
auto mech = def ;
if ( msg = = Msg : : Set )
mech = data . currentItem < UInt32 > ( ) ;
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
std : : string val ( s2t : : multi_out_to_sane ( ( int ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , MULTI_OUT_TYPE , & val [ 0 ] ) ;
2023-07-10 07:28:45 +00:00
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
2023-09-22 08:26:22 +00:00
Int32 now = cur , init = def , ind = 0 ,
2023-07-10 07:28:45 +00:00
curInd = distance < int > ( all , cur ) ,
defInd = distance < int > ( all , def ) ;
std : : list < Int32 > vals ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
vals . push_back ( all [ i ] ) ;
2023-09-22 08:26:22 +00:00
return CapSupGetAllResetEx < Int32 , Int32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_MULTI_OUT_TYPE > ( msg , data , vals , now , init , curInd , defInd ) ;
2023-07-10 07:28:45 +00:00
} ;
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_WAIT_TO_SCAN ) ! = ids . end ( ) )
{
m_query [ CapType ( CapTypeEx : : CAP_TYPE_EX_TO_BE_SCAN ) ] = m_query [ CapType : : AutoScan ] ;
m_caps [ CapType ( CapTypeEx : : CAP_TYPE_EX_TO_BE_SCAN ) ] = m_caps [ CapType : : AutoScan ] ;
}
2023-09-21 03:23:38 +00:00
2023-09-22 08:26:22 +00:00
m_query [ CapType ( CapTypeEx : : CAP_TYPE_EX_SCAN_WITH_HOLE ) ] = msgSupportGetAllSetReset ;
m_caps [ CapType ( CapTypeEx : : CAP_TYPE_EX_SCAN_WITH_HOLE ) ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
2023-07-10 07:28:45 +00:00
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
2023-09-22 08:26:22 +00:00
auto tobe = false ;
if ( msg = = Msg : : Set )
tobe = data . currentItem < Int32 > ( ) ;
2023-07-10 07:28:45 +00:00
int ret = SCANNER_ERR_OK ;
2023-09-22 08:26:22 +00:00
SET_SANE_OPT ( ret , scanner_ , RID_HOLE_L , & tobe ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : seqError ( ) ;
2023-07-10 07:28:45 +00:00
}
2023-09-22 08:26:22 +00:00
std : : vector < bool > all ;
GET_SANE_OPT ( bool , scanner_ , RID_HOLE_L , NULL , & all ) ;
BYTE tobe = all [ sane_opts : : RANGE_POS_CURRENT ] ; ;
return CapSupGetAllResetEx < BYTE , Int32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_SCAN_WITH_HOLE > ( msg , data , tobe , 0 ) ;
} ;
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_DEVICE_SERIAL_NO ) ! = ids . end ( ) )
{
m_query [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_ENCODE ) ] = m_query [ CapType : : SerialNumber ] ;
m_caps [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_ENCODE ) ] = m_caps [ CapType : : SerialNumber ] ;
}
2023-07-10 07:28:45 +00:00
2023-09-22 08:26:22 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_TIME_TO_SLEEP ) ! = ids . end ( ) )
{
m_query [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_POWER_LEVEL ) ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) ( CapTypeEx : : CAP_TYPE_EX_POWER_LEVEL ) ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int cur = SANE_POWER_MINUTES_30 , def = SANE_POWER_MINUTES_30 ;
std : : vector < int > all ;
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , TIME_TO_SLEEP , NULL , & sall ) ;
for ( auto & v : sall )
all . push_back ( s2t : : power_from_sane ( v . c_str ( ) ) ) ;
sall . clear ( ) ;
cur = all [ sane_opts : : RANGE_POS_CURRENT ] ;
def = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
if ( msg = = Msg : : Set )
def = data . currentItem < UInt32 > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : power_to_sane ( def ) ) ;
SET_SANE_OPT ( ret , scanner_ , TIME_TO_SLEEP , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
UInt32 now = cur , init = def , ind = 0 ,
curInd = distance < int > ( all , cur ) ,
defInd = distance < int > ( all , def ) ;
std : : list < UInt32 > vals ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
{
vals . push_back ( all [ i ] ) ;
}
return CapSupGetAllResetEx < UInt32 , UInt32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_POWER_LEVEL > ( msg , data , vals , now , init , curInd , defInd ) ;
} ;
}
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_FILL_BKG_MODE ) ! = ids . end ( ) )
{
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_BKG_FILLING_METHOD ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_BKG_FILLING_METHOD ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
if ( Msg : : Set = = msg ) {
auto convex = data . currentItem < Bool > ( ) ;
std : : string val ( s2t : : convex_to_sane ( ( bool ) convex ) ) ;
int ret = SCANNER_ERR_OK ;
SET_SANE_OPT ( ret , scanner_ , FILL_BKG_MODE , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
bool val = false , cur = false ;
Bool init = false ,
erase = false ;
std : : vector < std : : string > all ;
GET_SANE_OPT ( std : : string , scanner_ , FILL_BKG_MODE , NULL , & all ) ;
init = ( bool ) s2t : : convex_from_sane ( all [ sane_opts : : RANGE_POS_DEFAULT ] . c_str ( ) ) ;
erase = ( bool ) s2t : : convex_from_sane ( all [ sane_opts : : RANGE_POS_CURRENT ] . c_str ( ) ) ;
return CapSupGetAllResetEx < Bool , Bool , ( CapType ) CapTypeEx : : CAP_TYPE_EX_BKG_FILLING_METHOD > ( msg , data , { false , true } , erase , init , erase ? 1 : 0 , 0 ) ;
} ;
}
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_SHARPEN ) ! = ids . end ( ) )
{
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_SHARPEN ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_SHARPEN ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int cur = MULTI_OUT_NONE , def = MULTI_OUT_NONE ;
std : : vector < int > all ;
std : : vector < std : : string > sall ;
GET_SANE_OPT ( std : : string , scanner_ , SHARPEN , NULL , & sall ) ;
for ( auto & v : sall )
all . push_back ( s2t : : sharpen_from_sane ( v . c_str ( ) ) ) ;
sall . clear ( ) ;
cur = all [ sane_opts : : RANGE_POS_CURRENT ] ;
def = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
auto mech = def ;
if ( msg = = Msg : : Set )
mech = data . currentItem < UInt32 > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : sharpen_to_sane ( ( int ) mech ) ) ;
SET_SANE_OPT ( ret , scanner_ , SHARPEN , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
Int32 now = cur , init = def ,
curInd = distance < int > ( all , cur ) ,
defInd = distance < int > ( all , def ) ;
std : : list < Int32 > vals ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
vals . push_back ( all [ i ] ) ;
return CapSupGetAllResetEx < Int32 , Int32 , ( CapType ) CapTypeEx : : CAP_TYPE_EX_SHARPEN > ( msg , data , vals , now , init , curInd , defInd ) ;
} ;
}
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_FILTER ) ! = ids . end ( ) )
{
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_ENHANCE_COLOR ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_ENHANCE_COLOR ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
log_attr_access ( ( int ) type , ( int ) msg ) ;
int cur = FILTER_NONE , def = FILTER_NONE ;
std : : vector < int > vals ;
std : : vector < std : : string > svals ;
GET_SANE_OPT ( std : : string , scanner_ , FILTER , NULL , & svals ) ;
s2t : : filter_from_sane ( svals , vals , false ) ;
svals . clear ( ) ;
cur = vals [ sane_opts : : RANGE_POS_CURRENT ] ;
def = vals [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( Msg : : Set = = msg | | Msg : : Reset = = msg ) {
if ( Msg : : Set = = msg )
def = data . currentItem < UInt32 > ( ) ;
int ret = SCANNER_ERR_OK ;
std : : string val ( s2t : : enhance_to_sane ( ( int ) def ) ) ;
SET_SANE_OPT ( ret , scanner_ , FILTER , & val [ 0 ] ) ;
return ret = = SCANNER_ERR_OK ? success ( ) : badValue ( ) ;
}
std : : list < Filter > vs ;
Filter now = ( Filter ) ( cur ) , init = ( Filter ) ( def ) ;
UInt32 curInd = distance < int > ( vals , cur ) , defInd = distance < int > ( vals , def ) ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < vals . size ( ) ; + + i )
vs . push_back ( ( Filter ) vals [ i ] ) ;
UInt32 val = ( UInt32 ) now ;
return CapSupGetAllResetEx < UInt32 , Filter , ( CapType ) CapTypeEx : : CAP_TYPE_EX_ENHANCE_COLOR > ( msg , data , vs , val , init , curInd , defInd ) ;
} ;
}
2023-07-10 07:28:45 +00:00
}
2023-09-21 03:23:38 +00:00
init_caps_from_sane_directly ( ids ) ;
2023-07-10 07:28:45 +00:00
2023-09-21 03:23:38 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_FIRMWARE_VERSION ) ! = ids . end ( ) )
{
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_HARDWARE_VERSION ] = m_query [ ( CapType ) SANE_OPT_ID_FIRMWARE_VERSION ] ;
2023-09-21 08:11:58 +00:00
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_HARDWARE_VERSION ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result
{
return m_caps [ ( CapType ) SANE_OPT_ID_FIRMWARE_VERSION ] ( ( Twpp : : CapType ) SANE_OPT_ID_FIRMWARE_VERSION , msg , data ) ;
} ;
2023-09-21 03:23:38 +00:00
}
2023-07-10 07:28:45 +00:00
2023-09-21 03:23:38 +00:00
if ( std : : find ( ids . begin ( ) , ids . end ( ) , SANE_OPT_ID_DEVICE_IP_ADDR ) ! = ids . end ( ) )
{
m_query [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_IP ] = m_query [ ( CapType ) SANE_OPT_ID_DEVICE_IP_ADDR ] ;
2023-09-21 08:11:58 +00:00
m_caps [ ( CapType ) CapTypeEx : : CAP_TYPE_EX_IP ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result
{
return m_caps [ ( CapType ) SANE_OPT_ID_FIRMWARE_VERSION ] ( ( Twpp : : CapType ) SANE_OPT_ID_DEVICE_IP_ADDR , msg , data ) ;
} ;
2023-09-21 03:23:38 +00:00
}
2023-07-10 07:28:45 +00:00
# define SET_EXISTING_EXTENSION(name, cap) \
if ( m_query . count ( ( CapType ) SANE_OPT_ID_ # # name ) ) \
{ \
m_query [ ( CapType ) cap ] = m_query [ ( CapType ) SANE_OPT_ID_ # # name ] ; \
2023-09-21 08:11:58 +00:00
m_caps [ ( CapType ) cap ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result { \
return m_caps [ CapType ( ( int ) SANE_OPT_ID_ # # name ) ] ( ( Twpp : : CapType ) SANE_OPT_ID_ # # name , msg , data ) ; \
} ; \
2023-07-10 07:28:45 +00:00
org_func_ [ ( int ) cap ] = ( int ) SANE_OPT_ID_ # # name ; \
}
SET_EXISTING_EXTENSION ( EXCHANGE , CapTypeEx : : CAP_TYPE_EX_FLIP ) ;
SET_EXISTING_EXTENSION ( IS_ROTATE_BKG_180 , CapTypeEx : : CAP_TYPE_EX_ROTATE_BKG_180 ) ;
SET_EXISTING_EXTENSION ( IS_FILL_COLOR , CapTypeEx : : CAP_TYPE_EX_FILL_BLACK_BKG ) ;
SET_EXISTING_EXTENSION ( MARGIN , CapTypeEx : : CAP_TYPE_EX_EDGE_IDENT ) ;
SET_EXISTING_EXTENSION ( ANTI_NOISE_LEVEL , CapTypeEx : : CAP_TYPE_EX_ANTI_NOISE ) ;
SET_EXISTING_EXTENSION ( THRESHOLD , CapTypeEx : : CAP_TYPE_EX_THRESHOLD ) ;
SET_EXISTING_EXTENSION ( RID_HOLE , CapTypeEx : : CAP_TYPE_EX_FILL_HOLE ) ;
SET_EXISTING_EXTENSION ( NOISE_OPTIMIZE , CapTypeEx : : CAP_TYPE_EX_DETACH_NOISE ) ;
SET_EXISTING_EXTENSION ( NOISE_SIZE , CapTypeEx : : CAP_TYPE_EX_DETACH_NOISE_THRESHOLD ) ;
SET_EXISTING_EXTENSION ( RID_MULTIOUT_RED , CapTypeEx : : CAP_TYPE_EX_RID_RED ) ;
SET_EXISTING_EXTENSION ( RID_ANSWER_SHEET_RED , CapTypeEx : : CAP_TYPE_EX_RID_RED_HSV ) ;
SET_EXISTING_EXTENSION ( IS_CHECK_ASKEW , CapTypeEx : : CAP_TYPE_EX_SCREW_DETECT ) ;
SET_EXISTING_EXTENSION ( ASKEW_RANGE , CapTypeEx : : CAP_TYPE_EX_SCREW_DETECT_LEVEL ) ;
SET_EXISTING_EXTENSION ( IS_CHECK_STAPLE , CapTypeEx : : CAP_TYPE_EX_STAPLE_DETECT ) ;
SET_EXISTING_EXTENSION ( IS_CHECK_DOG_EAR , CapTypeEx : : CAP_TYPE_EX_DOGEAR_DETECT ) ;
SET_EXISTING_EXTENSION ( DARK_SAMPLE , CapTypeEx : : CAP_TYPE_EX_DARK_SAMPLE ) ;
SET_EXISTING_EXTENSION ( SPLIT , CapTypeEx : : CAP_TYPE_EX_IMAGE_SPLIT ) ;
SET_EXISTING_EXTENSION ( ERASE_BACKGROUND , CapTypeEx : : CAP_TYPE_EX_FADE_BKG ) ;
SET_EXISTING_EXTENSION ( BKG_COLOR_RANGE , CapTypeEx : : CAP_TYPE_EX_FADE_BKG_VALUE ) ;
SET_EXISTING_EXTENSION ( SIZE_CHECK , CapTypeEx : : CAP_TYPE_EX_SIZE_DETECT ) ;
SET_EXISTING_EXTENSION ( IS_MULTI_OUT , CapTypeEx : : CAP_TYPE_EX_MULTI_OUT ) ;
2023-09-21 03:23:38 +00:00
//m_query[(CapType)SANE_OPT_ID_DEVICE_SERIAL_NO] = m_query[CapType::SerialNumber];
//m_caps[(CapType)SANE_OPT_ID_DEVICE_SERIAL_NO] = m_caps[CapType::SerialNumber];
//org_func_[SANE_OPT_ID_DEVICE_SERIAL_NO] = (int)CapType::SerialNumber;
2023-07-10 07:28:45 +00:00
2023-09-21 03:23:38 +00:00
//m_query[(CapType)SANE_OPT_ID_FIRMWARE_VERSION] = m_query[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION];
//m_caps[(CapType)SANE_OPT_ID_FIRMWARE_VERSION] = m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION];
//org_func_[SANE_OPT_ID_FIRMWARE_VERSION] = (int)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION;
2023-07-10 07:28:45 +00:00
2023-09-21 03:23:38 +00:00
//m_query[(CapType)SANE_OPT_ID_DEVICE_IP_ADDR] = m_query[(CapType)CapTypeEx::CAP_TYPE_EX_IP];
//m_caps[(CapType)SANE_OPT_ID_DEVICE_IP_ADDR] = m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_IP];
//org_func_[SANE_OPT_ID_DEVICE_IP_ADDR] = (int)CapTypeEx::CAP_TYPE_EX_IP;
2023-07-10 07:28:45 +00:00
}
2023-09-21 03:23:38 +00:00
void huagao_ds : : init_caps_from_sane_directly ( const std : : vector < uint32_t > & ids )
2023-07-10 07:28:45 +00:00
{
for ( auto & v : ids )
{
value_type type = VAL_TYPE_NONE ;
value_limit limit = VAL_LIMIT_NONE ;
int bytes = 0 ;
bool rdo = false ;
2023-09-21 03:23:38 +00:00
if ( ! scanner_ - > get_option_info ( v , & type , & limit , & bytes , & rdo ) )
2023-07-10 07:28:45 +00:00
continue ;
2023-09-21 03:23:38 +00:00
//rdo = (limit & VAL_LIMIT_READONLY) == VAL_LIMIT_READONLY;
2023-07-10 07:28:45 +00:00
limit = ( value_limit ) ( limit & VAL_LIMIT_MASK ) ;
if ( type = = VAL_TYPE_BOOL )
{
if ( rdo )
{
m_query [ ( CapType ) v ] = msgSupportGetAll ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < bool > all ;
sane_opts : : get_opts < bool > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < bool > , & op ) ;
op . re_order ( ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Bool > ( type , Bool ( all [ sane_opts : : RANGE_POS_CURRENT ] ) ) ;
return success ( ) ;
} ;
}
else
{
m_query [ ( CapType ) v ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < bool > all ;
sane_opts : : get_opts < bool > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < bool > , & op ) ;
op . re_order ( ) ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
bool init = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
if ( msg = = Msg : : Set )
init = ( bool ) data . currentItem < Bool > ( ) ;
int ret = scanner_ - > set_value ( ( int ) type , & init ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
else if ( msg = = Msg : : GetCurrent | | msg = = Msg : : GetDefault )
{
Bool t ;
if ( msg = = Msg : : GetCurrent )
t = Bool ( all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
else
t = ( Bool ) all [ sane_opts : : RANGE_POS_DEFAULT ] ;
type = data . type ( ) ;
data = Capability : : createOneValue < Bool > ( type , t ) ;
return success ( ) ;
}
else
{
UInt32 ni = all [ sane_opts : : RANGE_POS_CURRENT ] ? 1 : 0 , ii = all [ sane_opts : : RANGE_POS_DEFAULT ] ? 1 : 0 ;
type = data . type ( ) ;
data = Capability : : createEnumeration < Bool > ( type , { FALSE , TRUE } , ni , ii ) ;
return success ( ) ;
}
} ;
}
}
else if ( type = = VAL_TYPE_INT )
{
// int -> Int32
if ( rdo )
{
m_query [ ( CapType ) v ] = msgSupportGetAll ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < int > all ;
Int32 val ;
sane_opts : : get_opts < int > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < int > , & op ) ;
op . re_order ( ) ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Int32 > ( type , val ) ;
return success ( ) ;
} ;
}
else
{
m_query [ ( CapType ) v ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < int > all ;
value_limit lmt ;
sane_opts : : get_opts < int > op ( & lmt , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < int > , & op ) ;
op . re_order ( ) ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
int val = ( int ) data . currentItem < Int32 > ( ) ;
if ( msg = = Msg : : Reset )
val = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
int ret = scanner_ - > set_value ( ( int ) type , & val ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Int32 > ( type , ( Int32 ) val ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
else if ( msg = = Msg : : GetCurrent | | msg = = Msg : : GetDefault )
{
Int32 val ;
if ( msg = = Msg : : GetCurrent )
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
else
copy_type ( val , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Int32 > ( type , val ) ;
return success ( ) ;
}
else
{
if ( lmt = = VAL_LIMIT_ENUM )
{
std : : list < Int32 > vals ;
UInt32 ni = distance < int > ( all , all [ sane_opts : : RANGE_POS_CURRENT ] ) ,
ii = distance < int > ( all , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
{
Int32 t ;
copy_type ( t , all [ i ] ) ;
vals . push_back ( t ) ;
}
type = data . type ( ) ;
data = Capability : : createEnumeration < Int32 > ( type , vals , ni , ii ) ;
}
else if ( lmt = = VAL_LIMIT_RANGE )
{
Int32 now , init , lower , upper , step ;
copy_type ( now , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
copy_type ( init , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
copy_type ( lower , all [ sane_opts : : RANGE_POS_LOWER ] ) ;
copy_type ( upper , all [ sane_opts : : RANGE_POS_UPPER ] ) ;
copy_type ( step , all [ sane_opts : : RANGE_POS_STEP ] ) ;
type = data . type ( ) ;
data = Capability : : createRange < Int32 > ( type , lower , upper , step , now , init ) ;
}
else
{
Int32 val ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Int32 > ( type , val ) ;
}
return success ( ) ;
}
} ;
}
}
else if ( type = = VAL_TYPE_FLOAT )
{
// float -> Fix32
if ( rdo )
{
m_query [ ( CapType ) v ] = msgSupportGetAll ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-10-20 07:21:17 +00:00
std : : vector < double > all ;
2023-07-10 07:28:45 +00:00
Fix32 val ;
2023-10-20 07:21:17 +00:00
sane_opts : : get_opts < double > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < double > , & op ) ;
2023-07-10 07:28:45 +00:00
op . re_order ( ) ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Fix32 > ( type , val ) ;
return success ( ) ;
} ;
}
else
{
m_query [ ( CapType ) v ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
2023-10-20 07:21:17 +00:00
std : : vector < double > all ;
2023-07-10 07:28:45 +00:00
value_limit lmt ;
2023-10-20 07:21:17 +00:00
sane_opts : : get_opts < double > op ( & lmt , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < double > , & op ) ;
2023-07-10 07:28:45 +00:00
op . re_order ( ) ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
float val = .0f ;
copy_type ( val , data . currentItem < Fix32 > ( ) ) ;
if ( msg = = Msg : : Reset )
val = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
double dbv = val ;
int ret = scanner_ - > set_value ( ( int ) type , & dbv ) ;
Fix32 fv ;
val = dbv ;
copy_type ( fv , val ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Fix32 > ( type , fv ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
else if ( msg = = Msg : : GetCurrent | | msg = = Msg : : GetDefault )
{
Fix32 val ;
if ( msg = = Msg : : GetCurrent )
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
else
copy_type ( val , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Fix32 > ( type , val ) ;
return success ( ) ;
}
else
{
type = data . type ( ) ;
if ( lmt = = VAL_LIMIT_ENUM )
{
std : : list < Fix32 > vals ;
2023-10-20 07:21:17 +00:00
UInt32 ni = distance < double > ( all , all [ sane_opts : : RANGE_POS_CURRENT ] ) ,
ii = distance < double > ( all , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
2023-07-10 07:28:45 +00:00
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
{
Fix32 t ;
copy_type ( t , all [ i ] ) ;
vals . push_back ( t ) ;
}
data = Capability : : createEnumeration < Fix32 > ( type , vals , ni , ii ) ;
}
else if ( lmt = = VAL_LIMIT_RANGE )
{
Fix32 now , init , lower , upper , step ;
copy_type ( now , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
copy_type ( init , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
copy_type ( lower , all [ sane_opts : : RANGE_POS_LOWER ] ) ;
copy_type ( upper , all [ sane_opts : : RANGE_POS_UPPER ] ) ;
copy_type ( step , all [ sane_opts : : RANGE_POS_STEP ] ) ;
data = Capability : : createRange < Fix32 > ( type , lower , upper , step , now , init ) ;
}
else
{
Fix32 val ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
data = Capability : : createOneValue < Fix32 > ( type , val ) ;
}
return success ( ) ;
}
} ;
}
}
else if ( type = = VAL_TYPE_STR )
{
// std::string -> Str255
if ( v = = SANE_OPT_ID_LOGIN | | v = = SANE_OPT_ID_LOGOUT )
{
m_query [ ( CapType ) v ] = MsgSupport : : Set ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
if ( msg ! = Msg : : Set )
{
if ( msg = = Msg : : Get )
{
data = Capability : : createArray < Str32 > ( type , 2 ) ;
return success ( ) ;
}
return { ReturnCode : : Failure , ConditionCode : : CapUnsupported } ;
}
Str32 n ( data . array < Str32 > ( ) . at ( 0 ) ) ,
p ( data . array < Str32 > ( ) . at ( 1 ) ) ;
char buf [ 64 ] = { 0 } ;
int ret = 0 ;
strcpy ( buf , n . data ( ) ) ;
strcpy ( buf + 32 , p . data ( ) ) ;
ret = scanner_ - > set_value ( ( int ) type , buf ) ;
if ( ret = = SCANNER_ERR_OK )
return success ( ) ;
return { RC : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
} ;
}
else if ( v = = SANE_OPT_ID_DRIVER_LOG | | v = = SANE_OPT_ID_DEVICE_LOG )
{
m_query [ ( CapType ) v ] = MsgSupport : : GetCurrent | MsgSupport : : Reset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
if ( msg = = Msg : : GetCurrent | | msg = = Msg : : Get )
{
Str255 str ;
if ( msg = = Msg : : Get ) { data = Capability : : createOneValue < Str255 > ( type , str ) ; return success ( ) ; }
std : : string path ( " " ) ;
int len = 0 ;
copy_type ( path , data . currentItem < Str255 > ( ) ) ;
len = path . length ( ) ;
if ( scanner_ - > get_value ( ( int ) type , & path [ 0 ] , & len ) ) return success ( ) ; else return { RC : : Failure , CC : : OperationError } ;
}
else if ( msg = = Msg : : Reset )
{
int tmp = 0 , ret = scanner_ - > set_value ( ( int ) type , & tmp ) ;
if ( ret = = SCANNER_ERR_OK )
return success ( ) ;
return { RC : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
}
return { ReturnCode : : Failure , ConditionCode : : CapUnsupported } ;
} ;
}
else if ( rdo )
{
m_query [ ( CapType ) v ] = msgSupportGetAll ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < std : : string > all ;
Str255 val ;
sane_opts : : get_opts < std : : string > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < std : : string > , & op ) ;
op . re_order ( ) ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Str255 > ( type , val ) ;
return success ( ) ;
} ;
}
else
{
m_query [ ( CapType ) v ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < std : : string > all ;
value_limit lmt ;
sane_opts : : get_opts < std : : string > op ( & lmt , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < std : : string > , & op ) ;
op . re_order ( ) ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
std : : string val ( " " ) ;
if ( msg = = Msg : : Set )
copy_type ( val , data . currentItem < Str255 > ( ) ) ;
else
val = all [ sane_opts : : RANGE_POS_DEFAULT ] ;
val . resize ( 255 ) ;
int ret = scanner_ - > set_value ( ( int ) type , & val [ 0 ] ) ;
Str255 rv ;
copy_type ( rv , val ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Str255 > ( type , rv ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
else if ( msg = = Msg : : GetCurrent | | msg = = Msg : : GetDefault )
{
Str255 val ;
if ( msg = = Msg : : GetCurrent )
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
else
copy_type ( val , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
type = data . type ( ) ;
data = Capability : : createOneValue < Str255 > ( type , val ) ;
return success ( ) ;
}
else
{
type = data . type ( ) ;
if ( lmt = = VAL_LIMIT_ENUM )
{
std : : list < Str255 > vals ;
UInt32 ni = distance < std : : string > ( all , all [ sane_opts : : RANGE_POS_CURRENT ] ) ,
ii = distance < std : : string > ( all , all [ sane_opts : : RANGE_POS_DEFAULT ] ) ;
for ( size_t i = sane_opts : : RANGE_POS_ENUM_BEGIN ; i < all . size ( ) ; + + i )
{
Str255 t ;
copy_type ( t , all [ i ] ) ;
vals . push_back ( t ) ;
}
data = Capability : : createEnumeration < Str255 > ( type , vals , ni , ii ) ;
}
else
{
Str255 val ;
copy_type ( val , all [ sane_opts : : RANGE_POS_CURRENT ] ) ;
data = Capability : : createOneValue < Str255 > ( type , val ) ;
}
return success ( ) ;
}
} ;
}
}
else if ( type = = VAL_TYPE_STREAM )
{
if ( rdo )
{
m_query [ ( CapType ) v ] = msgSupportGetAll ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < std : : string > all ;
sane_opts : : get_opts < std : : string > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < std : : string > , & op ) ;
op . re_order ( ) ;
type = data . type ( ) ;
if ( all [ sane_opts : : RANGE_POS_CURRENT ] . length ( ) )
{
size_t ind = 0 ;
data = Capability : : createArray < Int8 > ( type , all [ sane_opts : : RANGE_POS_CURRENT ] . length ( ) ) ;
for ( auto & c : all [ sane_opts : : RANGE_POS_CURRENT ] )
data . array < Int8 > ( ) [ ind + + ] = ( Int8 ) c ;
return success ( ) ;
}
else
return bummer ( ) ;
} ;
}
else
{
m_query [ ( CapType ) v ] = msgSupportGetAllSetReset ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
std : : vector < std : : string > all ;
sane_opts : : get_opts < std : : string > op ( NULL , & all ) ;
scanner_ - > get_value ( ( int ) type , sane_opts : : set_opt_value < std : : string > , & op ) ;
op . re_order ( ) ;
if ( msg = = Msg : : Set | | msg = = Msg : : Reset )
{
if ( data . array < Int8 > ( ) . size ( ) < all [ sane_opts : : RANGE_POS_CURRENT ] . length ( ) )
return badValue ( ) ;
Int8 * ptr = & data . array < Int8 > ( ) . at ( 0 ) ;
int ret = scanner_ - > set_value ( ( int ) type , ptr ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
else
{
if ( all [ sane_opts : : RANGE_POS_CURRENT ] . length ( ) )
{
size_t ind = 0 ;
type = data . type ( ) ;
data = Capability : : createArray < Int8 > ( type , all [ sane_opts : : RANGE_POS_CURRENT ] . length ( ) ) ;
for ( auto & c : all [ sane_opts : : RANGE_POS_CURRENT ] )
data . array < Int8 > ( ) [ ind + + ] = c ;
return success ( ) ;
}
else
return bummer ( ) ;
}
} ;
}
}
else if ( type = = VAL_TYPE_BUTTON )
{
m_query [ ( CapType ) v ] = MsgSupport : : Set ;
m_caps [ ( CapType ) v ] = [ this ] ( Twpp : : CapType type , Msg msg , Capability & data ) - > Result {
if ( msg = = Msg : : Set )
{
int val = 0 ,
ret = scanner_ - > set_value ( ( int ) type , & val ) ;
if ( ret )
return { ReturnCode : : Failure , huagao_ds : : condition_code_from_hg_error ( ret ) } ;
else
return success ( ) ;
}
return { ReturnCode : : Failure , ConditionCode : : BadProtocol } ;
} ;
}
}
}
std : : string huagao_ds : : get_config_file ( void )
{
# if defined(WIN32) || defined(_WIN64)
char * tmp = getenv ( " LOCALAPPDATA " ) ;
if ( tmp )
{
std : : string str ( " " ) ;
std : : string path ( tmp ) ;
path + = std : : string ( " \\ " ) + PRODUCT_VENDOR + " Scan \\ config \\ debug.cfg " ;
return std : : move ( path ) ;
}
else
{
char path [ MAX_PATH ] = { 0 } , * name = NULL ;
GetModuleFileNameA ( me_ , path , _countof ( path ) - 1 ) ;
name = strrchr ( path , ' \\ ' ) ;
if ( name + + = = NULL )
name = path ;
strcpy ( name , " debug.cfg " ) ;
return path ;
}
# else
return std : : move ( utils : : get_local_data_path ( ) + " /config/debug.cfg " ) ;
# endif
}
std : : string huagao_ds : : get_config_value ( const char * sec , const char * key )
{
char v [ 256 ] = { 0 } ;
std : : string cfg_f ( get_config_file ( ) ) ;
if ( ! cfg_f . empty ( ) )
GetPrivateProfileStringA ( sec , key , " " , v , _countof ( v ) - 1 , get_config_file ( ) . c_str ( ) ) ;
return v ;
}
2023-07-26 01:07:44 +00:00
DWORD huagao_ds : : get_config_number ( const char * sec , const char * key , DWORD def , DWORD empty )
2023-07-10 07:28:45 +00:00
{
std : : string cfg_f ( get_config_file ( ) ) ;
if ( cfg_f . empty ( ) )
2023-07-26 01:07:44 +00:00
return empty ;
2023-07-10 07:28:45 +00:00
else
2023-07-26 01:07:44 +00:00
return GetPrivateProfileIntA ( sec , key , def , get_config_file ( ) . c_str ( ) ) ;
2023-07-10 07:28:45 +00:00
}
int huagao_ds : : handle_scanner_event ( int ev , bool from_event_proc )
{
static int count_0 = 0 ;
ReturnCode rc = ReturnCode : : Success ;
int ret = 0 ;
if ( ev = = 0 )
count_0 + + ;
else
{
char msg [ 128 ] = { 0 } ;
if ( count_0 )
sprintf ( msg , " [%x]handle_scanner_event(0x0 +%d) \r \n ds::eventProcess(0x%x) \r \n " , GetCurrentThreadId ( ) , count_0 , ev ) ;
else
sprintf ( msg , " [%x]handle_scanner_event(0x%x) \r \n " , GetCurrentThreadId ( ) , ev ) ;
utils : : log_info ( msg , 0 ) ;
count_0 = 0 ;
}
switch ( ev )
{
case SANE_EVENT_WORKING :
scanner_status_ = SCANNER_STATUS_SCANNING ;
rc = notifyXferReady ( ) ;
//if (!Twpp::success(rc))
//{
// char msg[128] = { 0 };
// sprintf(msg, _countof(msg) - 1, "[%x]Warning: change state to XferReady failed with error %d while in state(%d), STOP scanning ...\r\n", GetCurrentThreadId(), rc, state());
// utils::log_info(msg, 0);
// // we stop scanning here ...
// scanner_->stop();
//}
break ;
case SANE_EVENT_UI_CLOSE_SETTING :
scanner_ - > ui_hide ( ) ;
if ( notify_close_ = = NOTIFY_ALWAYS )
{
utils : : to_log ( 1 , " close setting ui and notify close immediately. \r \n " ) ;
rc = notifyCloseCancel ( ) ;
}
else if ( notify_close_ = = NOTIFY_NONE )
{
utils : : to_log ( 1 , " close setting ui and notify close passively (wait eventProcess to do). \r \n " ) ;
notfify_close_ = true ;
}
else // if (notify_close_ == NOTIFY_AUTO)
{
utils : : to_log ( 1 , " close setting ui and notify close in auto mode. \r \n " ) ;
//if (has_event_called_)
// notfify_close_ = true;
//else
// rc = notifyCloseCancel();
notfify_close_ = true ;
if ( notify_close_thread_ . get ( ) & & notify_close_thread_ - > joinable ( ) )
notify_close_thread_ - > join ( ) ;
notify_close_thread_ . reset ( new std : : thread ( & huagao_ds : : notify_close_thread , this ) ) ;
}
//if(main_thread_id_ == GetCurrentThreadId())
// rc = notifyCloseCancel();
//else
//{
// HANDLE thrd = OpenThread(THREAD_ALL_ACCESS, FALSE, main_thread_id_);
// int err = -1;
// if (thrd)
// {
// if (QueueUserAPC(&huagao_ds::notify_close, thrd, (ULONG_PTR)this))
// err = 0;
// else
// err = GetLastError();
// CloseHandle(thrd);
// }
// utils::to_log(3, "Notify close setting UI in different thread(%x), invoke 'notifyCloseCancel' in enable-thread %x(%x), result %d\r\n", GetCurrentThreadId(), main_thread_id_, thrd, err);
//}
//if (!Twpp::success(rc))
//{
// rc = notifyXferReady(); // 好分数需要再通知 FAINT :( - modified on 2022-10-20
// if (!Twpp::success(rc))
// {
// char msg[128] = { 0 }, unk[20] = { 0 };
// sprintf(msg, _countof(msg) - 1, "[%x]yscan: notifyXferReady failed after setting UI closed with error %d\r\n", GetCurrentThreadId(), rc);
// utils::log_info(msg, 0);
// }
// rc = notifyCloseCancel();
//}
show_setting_ = false ;
break ;
case SANE_EVENT_UI_CLOSE_CANCEL :
//scanner_->stop();
//notifyCloseCancel(); // 修复点击进度<E8BF9B> ?取消"按钮, UI不能正常结束的BUG - added on 2023-02-14
//break;
case SANE_EVENT_UI_CLOSE_NORMAL :
case SANE_EVENT_SCAN_FINISHED :
//scanner_->ui_hide();
scanner_status_ = SCANNER_STATUS_STOPPED ; // notifyCloseCancel is not need, because it done in EndXfer
//if(show_setting_)
// notifyCloseCancel();
// notifyCloseOk();
break ;
case SANE_EVENT_UI_SCAN_COMMAND :
scanner_ - > ui_show_progress ( NULL , m_bIndicator ) ;
scanner_status_ = SCANNER_STATUS_SCAN_1 ;
app_trigger_event_ = false ;
if ( ( ret = scanner_ - > start ( ) ) )
{
char msg [ 128 ] = { 0 } , unk [ 20 ] = { 0 } ;
sprintf ( msg , " [%x - %s]Fatal: start scanning from setting UI failed with error %d \r \n " , GetCurrentThreadId ( ) , desc_state ( state ( ) , unk ) , ret ) ;
utils : : log_info ( msg , 1 ) ;
scanner_status_ = SCANNER_STATUS_STOPPED ;
if ( bUiOnly_ )
rc = notifyCloseCancel ( ) ;
if ( Twpp : : success ( rc ) )
{
scanner_status_ = SCANNER_STATUS_READY ;
}
else
{
sprintf ( msg , " [%x - %s]Warning: notifyCloseCancel failed with error %d after start scanning failed \r \n " , GetCurrentThreadId ( ) , desc_state ( state ( ) , unk ) , rc ) ;
utils : : log_info ( msg , 1 ) ;
}
}
else
{
notifyXferReady ( ) ; // scan from UI, should notify this state mannually
}
break ;
}
return 0 ;
}
int huagao_ds : : get_scanned_image_count ( DWORD timeout )
{
int cnt = scanner_ - > get_scanned_images ( timeout ) ;
//if (cnt == -1)
//{
// // This is a special value indicates the scanning is over
// cnt = 0;
// scanner_->ui_hide();
// notifyCloseCancel();
//}
return cnt ;
}
void huagao_ds : : trigger_ProcessEvent ( Twpp : : DataGroup dg , Twpp : : Dat dat , Twpp : : Msg msg )
{
ReturnCode rc ;
if ( state ( ) = = DsState : : Enabled & & scanner_status_ > = SCANNER_STATUS_SCAN_1 ) // in scanning events ...
{
// here ensure APP enter into XferImage process ...
if ( ! app_trigger_event_ & & scanner_status_ = = SCANNER_STATUS_STOPPED )
{
// scanning stopped, reset APP state to ready ...
scanner_status_ = SCANNER_STATUS_READY ;
rc = notifyCloseCancel ( ) ;
if ( ! Twpp : : success ( rc ) )
{
char info [ 128 ] = { 0 } , unk [ 20 ] = { 0 } ;
sprintf ( info , " [%x]Warning: notifyCloseCancel failed with error %s! \r \n " , GetCurrentThreadId ( ) , desc_return_code ( rc , unk ) ) ;
utils : : log_info ( info , 1 ) ;
}
}
else
{
// start scanning, expect frist TRIPLE is ProcessEvent ...
if ( dg = = DataGroup : : Control & & dat = = Dat : : Event & & msg = = Msg : : ProcessEvent & & scanner_status_ = = SCANNER_STATUS_SCAN_1 )
{
app_trigger_event_ = true ; // nothing else to do
utils : : log_info ( " Good! first event is (Control, Event, ProcessEvent) after start scanning ^_^. \r \n " , 1 ) ;
}
else if ( ! app_trigger_event_ )
{
int ev = 0 ;
if ( scanner_status_ = = SCANNER_STATUS_SCAN_1 )
utils : : log_info ( " Sorry, first event is not (Control, Event, ProcessEvent) after start scanning, we takeover it! \r \n " , 1 ) ;
if ( scanner_ . get ( ) )
{
ev = scanner_ - > get_event ( ) ;
if ( ev )
handle_scanner_event ( ev , true ) ;
}
}
}
}
else if ( state ( ) > = DsState : : XferReady & & scanner_status_ = = SCANNER_STATUS_STOPPED )
{
// here ensure APP return to ready state ...
if ( scanner_ . get ( ) & & scanner_ - > get_scanned_images ( 0 ) = = 0 )
{
rc = notifyCloseCancel ( ) ;
if ( ! Twpp : : success ( rc ) )
{
char info [ 128 ] = { 0 } , unk [ 20 ] = { 0 } ;
sprintf ( info , " [%x]Warning: notifyCloseCancel failed with error %s when scanner is stopped! \r \n " , GetCurrentThreadId ( ) , desc_return_code ( rc , unk ) ) ;
utils : : log_info ( info , 1 ) ;
}
}
}
}
bool huagao_ds : : take_and_reset_notify_close_flag ( void )
{
std : : lock_guard < std : : mutex > lock ( notify_close_lock_ ) ;
bool notify = notfify_close_ ;
if ( notfify_close_ )
notfify_close_ = false ;
return notify ;
}
void huagao_ds : : notify_close_thread ( void )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1000 ) ) ;
if ( take_and_reset_notify_close_flag ( ) )
{
notifyCloseCancel ( ) ;
utils : : to_log ( 1 , " Trigger notifyCloseCancel in custom thread! \r \n " ) ;
}
else
{
utils : : to_log ( 1 , " Good! Trigger notifyCloseCancel in eventProcess ^_^ \r \n " ) ;
}
}