2022-06-15 03:04:40 +00:00
|
|
|
|
#include "scanner.h"
|
|
|
|
|
|
|
|
|
|
#include <Windows.h>
|
2022-10-08 09:20:16 +00:00
|
|
|
|
#include <Shlwapi.h> // for PathFileExistsW
|
2022-06-15 03:04:40 +00:00
|
|
|
|
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
|
|
|
|
|
#include <sane/sane_option_definitions.h>
|
|
|
|
|
#include "../../code_device/hgsane/sane_hg_mdw.h"
|
|
|
|
|
#include "sane_option_trans.h"
|
|
|
|
|
#include <chrono>
|
2022-06-18 00:54:01 +00:00
|
|
|
|
#include <mutex>
|
2022-06-18 08:48:41 +00:00
|
|
|
|
#include "DlgIndicator.h"
|
2022-06-20 07:17:55 +00:00
|
|
|
|
#include "DlgSetting.h"
|
2022-07-01 07:24:58 +00:00
|
|
|
|
#include "gb_json.h"
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-10-08 09:20:16 +00:00
|
|
|
|
#pragma comment(lib, "Shlwapi.lib")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
|
|
|
|
|
|
2022-10-07 09:51:09 +00:00
|
|
|
|
#define SET_SANE_OPT_ID(id, id_name, name, val, extension) \
|
|
|
|
|
if(strcmp(SANE_STD_OPT_NAME_##name, val) == 0) \
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{ \
|
|
|
|
|
id_name##_id_ = id; \
|
|
|
|
|
extension(id); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-19 06:16:34 +00:00
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
void __stdcall log_info(const wchar_t* info, int level);
|
2022-06-18 00:54:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// callback
|
2022-06-20 07:17:55 +00:00
|
|
|
|
extern "C"
|
|
|
|
|
{
|
|
|
|
|
extern SANE_Status inner_sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize);
|
|
|
|
|
extern void inner_sane_exit(void);
|
|
|
|
|
extern SANE_Status inner_sane_get_devices(const SANE_Device*** device_list, SANE_Bool local_only);
|
|
|
|
|
extern SANE_Status inner_sane_open(SANE_String_Const devicename, SANE_Handle* handle);
|
|
|
|
|
extern void inner_sane_close(SANE_Handle handle);
|
|
|
|
|
extern const SANE_Option_Descriptor* inner_sane_get_option_descriptor(SANE_Handle handle, SANE_Int option);
|
|
|
|
|
extern SANE_Status inner_sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info);
|
|
|
|
|
extern SANE_Status inner_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params);
|
|
|
|
|
extern SANE_Status inner_sane_start(SANE_Handle handle);
|
|
|
|
|
extern SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length);
|
|
|
|
|
extern void inner_sane_cancel(SANE_Handle handle);
|
|
|
|
|
extern SANE_Status inner_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking);
|
|
|
|
|
extern SANE_Status inner_sane_get_select_fd(SANE_Handle handle, SANE_Int* fd);
|
|
|
|
|
extern SANE_String_Const inner_sane_strstatus(SANE_Status status);
|
|
|
|
|
|
|
|
|
|
extern SANE_Status inner_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param);
|
|
|
|
|
extern SANE_Status inner_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-18 00:54:01 +00:00
|
|
|
|
namespace callback
|
|
|
|
|
{
|
|
|
|
|
static std::mutex cb_lock_;
|
|
|
|
|
typedef struct _scanner_inst
|
|
|
|
|
{
|
|
|
|
|
SANE_Handle dev;
|
|
|
|
|
scanner* invoker;
|
|
|
|
|
|
|
|
|
|
bool operator==(const SANE_Handle& h)
|
|
|
|
|
{
|
|
|
|
|
return dev == h;
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const scanner* obj)
|
|
|
|
|
{
|
|
|
|
|
return invoker == obj;
|
|
|
|
|
}
|
|
|
|
|
}SCNINST;
|
|
|
|
|
std::vector<SCNINST> g_scanner_instances;
|
|
|
|
|
|
|
|
|
|
int sane_event_callback( // 注册回调的对象,需要保证该回调是多线程安全的
|
|
|
|
|
SANE_Handle hdev // 产生事件的设备句柄
|
|
|
|
|
, int code // 回调事件代码
|
|
|
|
|
, void* data // 回调事件数据,根据事件代码有所不同,参照具体事件定义
|
|
|
|
|
, unsigned int* len // 数据长度(字节),或者event_data的缓冲区长度,详细请看相应的事件代码
|
|
|
|
|
, void* param // 用户自定义数据,与调用sane_init_ex传入时的保持一致
|
|
|
|
|
) // 返回值依不同的事件代码而定,通常为“0”
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
|
|
|
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), hdev);
|
|
|
|
|
|
|
|
|
|
if (it != g_scanner_instances.end())
|
2022-07-02 09:27:21 +00:00
|
|
|
|
return it->invoker->handle_device_event(code, data, len);
|
2022-06-18 00:54:01 +00:00
|
|
|
|
else
|
2022-09-21 08:44:41 +00:00
|
|
|
|
{
|
|
|
|
|
wchar_t msg[218] = { 0 };
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"Lost device(0x%08X) when event(%u) occurs!\r\n", hdev, code);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
|
2022-06-18 00:54:01 +00:00
|
|
|
|
return 0;
|
2022-09-21 08:44:41 +00:00
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
}
|
|
|
|
|
void reg_callback(SANE_Handle dev, scanner* invoker)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
|
|
|
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), dev);
|
|
|
|
|
if (it == g_scanner_instances.end())
|
|
|
|
|
{
|
|
|
|
|
SCNINST inst;
|
|
|
|
|
|
|
|
|
|
inst.dev = dev;
|
|
|
|
|
inst.invoker = invoker;
|
|
|
|
|
g_scanner_instances.push_back(inst);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
it->invoker = invoker;
|
|
|
|
|
}
|
|
|
|
|
void unreg_callback(scanner* invoker)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
|
|
|
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), invoker);
|
|
|
|
|
if (it != g_scanner_instances.end())
|
|
|
|
|
g_scanner_instances.erase(it);
|
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
const char* name;
|
|
|
|
|
const char* title;
|
|
|
|
|
}g_opts[] = { {SANE_STD_OPT_NAME_RESTORE , OPTION_TITLE_HFMRSZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_HELP , OPTION_TITLE_BZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_MULTI_OUT , OPTION_TITLE_DLSC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_MULTI_OUT_TYPE , OPTION_TITLE_DLSCLX}
|
|
|
|
|
, {SANE_STD_OPT_NAME_COLOR_MODE , OPTION_TITLE_YSMS}
|
|
|
|
|
, {SANE_STD_OPT_NAME_BINARY_THRESHOLD , OPTION_TITLE_HBTXYZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_REVERSE_01 , OPTION_TITLE_HBTXFSSC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_FILTER , OPTION_TITLE_HDHHBTX_CSYZQ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_MULTIOUT_RED , OPTION_TITLE_24WCSTX_DLSCCH}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED , OPTION_TITLE_24WCSTX_DTKCH}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ERASE_BACKGROUND , OPTION_TITLE_BJYC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_BKG_COLOR_RANGE , OPTION_TITLE_BJSCFDFW}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SHARPEN , OPTION_TITLE_RHYMH}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_MORR , OPTION_TITLE_QCMW}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_GRID , OPTION_TITLE_CWW}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ERROR_EXTENSION , OPTION_TITLE_CWKS}
|
|
|
|
|
, {SANE_STD_OPT_NAME_NOISE_OPTIMIZE , OPTION_TITLE_HBTXZDYH}
|
|
|
|
|
, {SANE_STD_OPT_NAME_NOISE_SIZE , OPTION_TITLE_ZDYHCC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_PAPER , OPTION_TITLE_ZZCC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA , OPTION_TITLE_ZDYSMQY}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT , OPTION_TITLE_SMQYZCmm}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT , OPTION_TITLE_SMQYYCmm}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_TOP , OPTION_TITLE_SMQYSCmm}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM , OPTION_TITLE_SMQYXCmm}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SIZE_CHECK , OPTION_TITLE_CCJC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_PAGE , OPTION_TITLE_SMYM}
|
|
|
|
|
, {SANE_STD_OPT_NAME_DISCARD_BLANK_SENS , OPTION_TITLE_TGKBYLMD}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RESOLUTION , OPTION_TITLE_FBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_TIME_TO_SLEEP , OPTION_TITLE_XMSJ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IMAGE_QUALITY , OPTION_TITLE_HZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_EXCHANGE ,OPTION_TITLE_JHZFM}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SPLIT ,OPTION_TITLE_TXCF }
|
|
|
|
|
, {SANE_STD_OPT_NAME_ANTI_SKEW , OPTION_TITLE_ZDJP}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA , OPTION_TITLE_QYSDQX}
|
|
|
|
|
, {SANE_STD_OPT_NAME_GAMMA , OPTION_TITLE_JMZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_BRIGHTNESS , OPTION_TITLE_LDZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_CONTRAST , OPTION_TITLE_DBD}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_PHOTO_MODE , OPTION_TITLE_ZPMS}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ERASE_BLACK_FRAME , OPTION_TITLE_XCHK}
|
|
|
|
|
, {SANE_STD_OPT_NAME_DARK_SAMPLE , OPTION_TITLE_SSYZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_THRESHOLD , OPTION_TITLE_YZ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL , OPTION_TITLE_BJKZDJ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_MARGIN , OPTION_TITLE_BYSJ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_FILL_BKG_MODE , OPTION_TITLE_BJTCFS}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_ANTI_PERMEATE , OPTION_TITLE_FZST}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL , OPTION_TITLE_FZSTDJ}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_HOLE_L , OPTION_TITLE_CKYCZC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L , OPTION_TITLE_ZCCKSSFWZFMBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_HOLE_R , OPTION_TITLE_CKYCYC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R , OPTION_TITLE_YCCKSSFWZFMBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_HOLE_T , OPTION_TITLE_CKYCSC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T , OPTION_TITLE_SCCKSSFWZFMBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_RID_HOLE_B , OPTION_TITLE_CKYCXC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B , OPTION_TITLE_XCCKSSFWZFMBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_FILL_COLOR , OPTION_TITLE_SCTC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK , OPTION_TITLE_CSBJC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE , OPTION_TITLE_SZTPCL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_CHECK_STAPLE , OPTION_TITLE_ZDJC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SCAN_MODE , OPTION_TITLE_SMZS}
|
|
|
|
|
, {SANE_STD_OPT_NAME_SCAN_COUNT , OPTION_TITLE_SMSL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_TEXT_DIRECTION , OPTION_TITLE_WGFX}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_ROTATE_BKG_180 , OPTION_TITLE_BMXZ180}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR , OPTION_TITLE_ZJJC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_DOG_EAR_SIZE , OPTION_TITLE_ZJDX}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_CHECK_ASKEW , OPTION_TITLE_WXJC}
|
|
|
|
|
, {SANE_STD_OPT_NAME_ASKEW_RANGE , OPTION_TITLE_WXRRD}
|
|
|
|
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH , OPTION_TITLE_FZQD}
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , OPTION_TITLE_ZDFZQD}
|
|
|
|
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , OPTION_TITLE_JZSBL}
|
|
|
|
|
, {SANE_STD_OPT_NAME_WAIT_TO_SCAN , OPTION_TITLE_DZSM}
|
|
|
|
|
},
|
|
|
|
|
g_discard[] = { {SANE_STD_OPT_NAME_REVERSE_01 , "\351\273\221\347\231\275\345\233\276\345\203\217\345\217\215\350\211\262\350\276\223\345\207\272\357\274\210\346\255\243\345\270\270\351\242\234\350\211\262\344\270\272\357\274\2320-\351\273\221\350\211\262\357\274\2331-\347\231\275\350\211\262\357\274\211"} // 黑白图像反色输出(正常颜色为:0-黑色;1-白色)
|
|
|
|
|
, {SANE_STD_OPT_NAME_FILTER , "\347\201\260\345\272\246\346\210\226\351\273\221\347\231\275\345\233\276\345\203\217 - \351\231\244\350\211\262"} // 灰度或黑白图像 - 除色
|
|
|
|
|
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , "\350\207\252\345\212\250\346\220\223\347\272\270\345\274\272\345\272\246"} // 自动搓纸强度
|
|
|
|
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , "\346\220\223\347\272\270\351\230\210\345\200\274"} // " 搓纸阈值"
|
|
|
|
|
};
|
|
|
|
|
const char* __stdcall option_title_2_name(const char* title)
|
|
|
|
|
{
|
|
|
|
|
while (*title == ' ')
|
|
|
|
|
title++;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < _countof(g_discard); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(title, g_discard[i].title) == 0)
|
|
|
|
|
return g_discard[i].name;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < _countof(g_opts); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(title, g_opts[i].title) == 0)
|
|
|
|
|
return g_opts[i].name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
const char* __stdcall option_name_2_title(const char* name)
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < _countof(g_opts); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(name, g_opts[i].name) == 0)
|
|
|
|
|
return g_opts[i].title;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// class scanner
|
|
|
|
|
scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
|
2022-07-02 09:27:21 +00:00
|
|
|
|
, dpi_(200), tmp_path_(L""), img_ind_(0)
|
2022-09-19 06:16:34 +00:00
|
|
|
|
, scanner_name_(L""), cfg_(NULL), is_ui_wait_img_(false), is_scanning_(false)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-07-01 07:24:58 +00:00
|
|
|
|
cfg_ = new gb::sane_config();
|
2022-06-16 08:04:58 +00:00
|
|
|
|
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
|
2022-09-23 06:17:41 +00:00
|
|
|
|
{
|
|
|
|
|
char* tmp = getenv("LOCALAPPDATA");
|
|
|
|
|
|
|
|
|
|
if (tmp)
|
|
|
|
|
{
|
|
|
|
|
tmp_path_ = local_trans::a2u(tmp) + L"\\";
|
|
|
|
|
tmp_path_ += local_trans::a2u(PRODUCT_VENDOR) + L"Scan\\";
|
|
|
|
|
CreateDirectoryW(tmp_path_.c_str(), NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-01 07:24:58 +00:00
|
|
|
|
cfg_path_ = tmp_path_ + L"config";
|
|
|
|
|
CreateDirectoryW(cfg_path_.c_str(), NULL);
|
|
|
|
|
cfg_path_ += L"\\";
|
2022-06-16 08:04:58 +00:00
|
|
|
|
tmp_path_ += L"imgs";
|
|
|
|
|
CreateDirectoryW(tmp_path_.c_str(), NULL);
|
|
|
|
|
tmp_path_ += L"\\";
|
2022-06-23 06:01:28 +00:00
|
|
|
|
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
2022-06-29 08:13:05 +00:00
|
|
|
|
img_fmt_.compress.compression = SANE_COMPRESSION_NONE;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
err_ = open();
|
|
|
|
|
}
|
|
|
|
|
scanner::~scanner()
|
2022-06-18 00:54:01 +00:00
|
|
|
|
{
|
2022-09-23 06:17:41 +00:00
|
|
|
|
close();
|
2022-07-01 07:24:58 +00:00
|
|
|
|
if (cfg_)
|
|
|
|
|
delete cfg_;
|
2022-06-18 00:54:01 +00:00
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
std::string scanner::get_scanner_name(SCANNERID id)
|
|
|
|
|
{
|
|
|
|
|
ScannerInfo* devs = NULL;
|
|
|
|
|
long count = 0;
|
|
|
|
|
std::string name("");
|
|
|
|
|
|
|
|
|
|
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_INSUFFICIENT_MEMORY)
|
|
|
|
|
{
|
|
|
|
|
count++;
|
|
|
|
|
devs = new ScannerInfo[count];
|
|
|
|
|
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_OK)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (devs[i].vid == GET_SCANNER_VID(id) &&
|
|
|
|
|
devs[i].pid == GET_SCANNER_PID(id))
|
|
|
|
|
{
|
|
|
|
|
name = devs[i].name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
delete[] devs;
|
|
|
|
|
}
|
2022-10-07 09:51:09 +00:00
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
value_type scanner::from_sane_type(SANE_Value_Type type)
|
|
|
|
|
{
|
|
|
|
|
if (type == SANE_TYPE_BOOL)
|
|
|
|
|
return VAL_TYPE_BOOL;
|
|
|
|
|
else if (type == SANE_TYPE_INT)
|
|
|
|
|
return VAL_TYPE_INT;
|
|
|
|
|
else if (type == SANE_TYPE_FIXED)
|
|
|
|
|
return VAL_TYPE_FLOAT;
|
|
|
|
|
else if (type == SANE_TYPE_STRING)
|
|
|
|
|
return VAL_TYPE_STR;
|
|
|
|
|
else
|
|
|
|
|
return VAL_TYPE_NONE;
|
|
|
|
|
}
|
|
|
|
|
value_limit scanner::from_sane_constraint(SANE_Constraint_Type type)
|
|
|
|
|
{
|
|
|
|
|
if (type == SANE_CONSTRAINT_RANGE)
|
|
|
|
|
return VAL_LIMIT_RANGE;
|
|
|
|
|
else if (type == SANE_CONSTRAINT_STRING_LIST || type == SANE_CONSTRAINT_WORD_LIST)
|
|
|
|
|
return VAL_LIMIT_ENUM;
|
|
|
|
|
else
|
|
|
|
|
return VAL_LIMIT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int __stdcall scanner::to_int(SANE_Int v)
|
|
|
|
|
{
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
float __stdcall scanner::to_float(SANE_Fixed v)
|
|
|
|
|
{
|
2022-07-18 02:55:01 +00:00
|
|
|
|
return (float)SANE_UNFIX(v);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
void __stdcall scanner::ui_callback(int uev, void* sender, void* param)
|
2022-06-18 08:48:41 +00:00
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
((scanner*)param)->on_ui_event(uev, sender);
|
2022-06-18 08:48:41 +00:00
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
bool __stdcall scanner::is_option_float(int sn, void* param)
|
|
|
|
|
{
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor((SANE_Handle)param, sn);
|
|
|
|
|
|
|
|
|
|
if (desc)
|
|
|
|
|
return desc->type == SANE_TYPE_FIXED;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
// IRef
|
|
|
|
|
COM_API_IMPLEMENT(scanner, long, add_ref(void))
|
|
|
|
|
{
|
|
|
|
|
return refer::add_ref();
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, long, release(void))
|
|
|
|
|
{
|
|
|
|
|
return refer::release();
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-08 09:20:16 +00:00
|
|
|
|
void scanner::transport_config_file(void)
|
|
|
|
|
{
|
|
|
|
|
size_t pos = scanner_name_.find(L" - ");
|
|
|
|
|
std::wstring pid(L"G"), old(L"");
|
|
|
|
|
|
|
|
|
|
if (pos == std::wstring::npos)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pid += scanner_name_.substr(pos + 3);
|
|
|
|
|
if (scanner_name_.find(L"HUAGOSCAN ") != std::wstring::npos)
|
|
|
|
|
{
|
|
|
|
|
old = local_trans::a2u("\345\215\216\351\253\230\346\211\253\346\217\217\344\273\252\342\200\224", CP_UTF8);
|
|
|
|
|
}
|
|
|
|
|
else if (scanner_name_.find(L"LANXUMSCAN ") != std::wstring::npos)
|
|
|
|
|
{
|
|
|
|
|
old = local_trans::a2u("\347\253\213\346\200\235\350\276\260\346\211\253\346\217\217\344\273\252\342\200\224", CP_UTF8);
|
|
|
|
|
pid += L"S";
|
|
|
|
|
}
|
|
|
|
|
old += pid;
|
|
|
|
|
if (PathFileExistsW((cfg_path_ + old).c_str()))
|
|
|
|
|
{
|
|
|
|
|
log_info((L"Rename config file '" + old + L"' to '" + scanner_name_.substr(0, pos) + L"'\r\n").c_str(), 0);
|
|
|
|
|
MoveFileW((cfg_path_ + old).c_str(), (cfg_path_ + scanner_name_.substr(0, pos)).c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
void scanner::update_config(void)
|
|
|
|
|
{
|
|
|
|
|
std::string notice("");
|
|
|
|
|
cfg_->update(&scanner::is_option_float, handle_, &callback::option_title_2_name, ¬ice);
|
|
|
|
|
if (notice.length())
|
|
|
|
|
{
|
|
|
|
|
std::wstring msg(L"\u4E0B\u5217\u914D\u7F6E\u6570\u636E\u9519\u8BEF\uFF0C\u5DF2\u7ECF\u6062\u590D\u5230\u9ED8\u8BA4\u503C\u3002\u5982\u679C\u9700\u8981\uFF0C\u8BF7\u91CD\u65B0\u8BBE\u7F6E\uFF1A\r\n\r\n");
|
|
|
|
|
size_t pos = notice.find("\r\n");
|
|
|
|
|
|
|
|
|
|
while (pos != std::string::npos)
|
|
|
|
|
{
|
|
|
|
|
msg += local_trans::a2u(callback::option_name_2_title(notice.substr(0, pos).c_str()), CP_UTF8) + L"\r\n";
|
|
|
|
|
notice.erase(0, pos + 2);
|
|
|
|
|
pos = notice.find("\r\n");
|
|
|
|
|
}
|
|
|
|
|
MessageBoxW(NULL, msg.c_str(), L"\u52A0\u8F7D\u914D\u7F6E", MB_OK | MB_ICONINFORMATION);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-01 07:24:58 +00:00
|
|
|
|
void scanner::load_config(const wchar_t* file)
|
|
|
|
|
{
|
|
|
|
|
cfg_->load_from_file(file);
|
2022-10-08 06:13:09 +00:00
|
|
|
|
update_config();
|
2022-07-01 07:24:58 +00:00
|
|
|
|
}
|
|
|
|
|
void scanner::save_config(const wchar_t* file)
|
|
|
|
|
{
|
|
|
|
|
cfg_->save_to(file);
|
|
|
|
|
}
|
|
|
|
|
void scanner::apply_config(void)
|
|
|
|
|
{
|
2022-10-08 06:13:09 +00:00
|
|
|
|
std::string n(""), v(""), ver(cfg_->get_version());
|
2022-09-27 04:35:37 +00:00
|
|
|
|
std::wstring notice(L"");
|
2022-10-08 06:13:09 +00:00
|
|
|
|
if (cfg_->first_config(n, v))
|
2022-07-01 07:24:58 +00:00
|
|
|
|
{
|
|
|
|
|
do
|
|
|
|
|
{
|
2022-10-08 06:13:09 +00:00
|
|
|
|
int id = cfg_->id_from_name(n.c_str());
|
2022-07-01 07:24:58 +00:00
|
|
|
|
if (id != -1)
|
|
|
|
|
{
|
|
|
|
|
void* data = &v[0];
|
2022-09-27 01:48:57 +00:00
|
|
|
|
SANE_Fixed fixed = 0;
|
2022-07-01 07:24:58 +00:00
|
|
|
|
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, id);
|
|
|
|
|
if (desc)
|
|
|
|
|
{
|
2022-10-08 06:13:09 +00:00
|
|
|
|
char* buf = NULL;
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
2022-07-01 07:24:58 +00:00
|
|
|
|
if (desc->type == SANE_TYPE_STRING)
|
|
|
|
|
{
|
|
|
|
|
buf = new char[desc->size + 4];
|
|
|
|
|
memset(buf, 0, desc->size + 4);
|
|
|
|
|
strcpy(buf, v.c_str());
|
|
|
|
|
data = buf;
|
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
hg_sane_middleware::instance()->set_option(handle_, id, SANE_ACTION_SET_VALUE, data, &after);
|
|
|
|
|
|
2022-07-01 07:24:58 +00:00
|
|
|
|
if (buf)
|
|
|
|
|
delete[] buf;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
} while (cfg_->next_config(n, v));
|
2022-07-01 07:24:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
void scanner::on_ui_event(int uev, void* sender)
|
2022-06-18 08:48:41 +00:00
|
|
|
|
{
|
2022-09-20 04:41:32 +00:00
|
|
|
|
bool indicator = sender == indicator_.get();
|
|
|
|
|
if (prev_start_result_ != SANE_STATUS_GOOD && indicator)
|
2022-07-04 08:31:37 +00:00
|
|
|
|
indicator_.reset();
|
|
|
|
|
else
|
2022-09-19 06:16:34 +00:00
|
|
|
|
{
|
|
|
|
|
if (/*events_.count() > 5 && !is_ui_wait_img_ &&*/
|
2022-09-20 08:23:31 +00:00
|
|
|
|
(uev == SANE_EVENT_UI_CLOSE_CANCEL || uev == SANE_EVENT_UI_CLOSE_NORMAL || uev == SANE_EVENT_UI_CLOSE_SETTING))
|
2022-09-19 06:16:34 +00:00
|
|
|
|
{
|
|
|
|
|
events_.clear();
|
|
|
|
|
ui_hide();
|
2022-09-20 04:41:32 +00:00
|
|
|
|
if(indicator)
|
|
|
|
|
events_.save(SANE_EVENT_SCAN_FINISHED);
|
|
|
|
|
else
|
|
|
|
|
events_.save(SANE_EVENT_UI_CLOSE_SETTING);
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
2022-09-20 04:41:32 +00:00
|
|
|
|
else
|
|
|
|
|
events_.save(uev);
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
2022-06-18 08:48:41 +00:00
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
int scanner::open(void)
|
|
|
|
|
{
|
|
|
|
|
int ret = close();
|
|
|
|
|
std::string name(scanner::get_scanner_name(id_));
|
|
|
|
|
|
2022-06-20 07:17:55 +00:00
|
|
|
|
scanner_name_ = L"";
|
2022-06-15 03:04:40 +00:00
|
|
|
|
if (name.empty())
|
|
|
|
|
return SCANNER_ERR_DEVICE_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
2022-10-08 09:20:16 +00:00
|
|
|
|
size_t pid = scanner_name_.find(L" - ");
|
|
|
|
|
if (pid == -1)
|
|
|
|
|
pid = scanner_name_.length();
|
|
|
|
|
|
|
|
|
|
transport_config_file();
|
2022-06-18 00:54:01 +00:00
|
|
|
|
callback::reg_callback(handle_, this);
|
2022-09-21 08:44:41 +00:00
|
|
|
|
scanner_name_ = local_trans::a2u(name.c_str(), CP_UTF8);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
ret = init_options_id();
|
2022-10-08 09:20:16 +00:00
|
|
|
|
load_config((cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str());
|
2022-09-23 06:17:41 +00:00
|
|
|
|
apply_config();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-09-22 08:25:03 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8));
|
|
|
|
|
MessageBoxW(NULL, msg.c_str(), L"\u6253\u5F00\u5931\u8D25", MB_OK | MB_ICONERROR);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
int scanner::close(void)
|
|
|
|
|
{
|
2022-09-21 08:44:41 +00:00
|
|
|
|
callback::unreg_callback(this);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
if (handle_)
|
2022-09-23 06:17:41 +00:00
|
|
|
|
{
|
2022-06-15 03:04:40 +00:00
|
|
|
|
hg_sane_middleware::instance()->close_device(handle_);
|
2022-09-23 06:17:41 +00:00
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
handle_ = NULL;
|
|
|
|
|
ex_id_ = EXTENSION_ID_BASE;
|
|
|
|
|
|
|
|
|
|
return SCANNER_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
int scanner::init_options_id(void)
|
|
|
|
|
{
|
|
|
|
|
SANE_Int op_id = 1;
|
|
|
|
|
const SANE_Option_Descriptor* desc = NULL;
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
|
|
|
|
|
#define SET_OPT_ID(var, predef, func) \
|
2022-10-07 09:51:09 +00:00
|
|
|
|
SET_SANE_OPT_ID(op_id, var, predef, desc->name, func)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, op_id)))
|
|
|
|
|
{
|
2022-07-01 07:24:58 +00:00
|
|
|
|
void* val = hg_sane_middleware::instance()->get_def_value(handle_, op_id);
|
|
|
|
|
if (val)
|
|
|
|
|
{
|
|
|
|
|
size_t len = 0;
|
|
|
|
|
switch (desc->type)
|
|
|
|
|
{
|
|
|
|
|
case SANE_TYPE_BOOL:
|
|
|
|
|
len = sizeof(SANE_Bool);
|
|
|
|
|
break;
|
|
|
|
|
case SANE_TYPE_INT:
|
|
|
|
|
len = sizeof(SANE_Int);
|
|
|
|
|
break;
|
|
|
|
|
case SANE_TYPE_FIXED:
|
|
|
|
|
len = sizeof(SANE_Fixed);
|
|
|
|
|
break;
|
|
|
|
|
case SANE_TYPE_STRING:
|
|
|
|
|
len = lstrlenA((char*)val);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (len)
|
2022-10-08 06:13:09 +00:00
|
|
|
|
cfg_->set_default_value(op_id, desc->name, (char*)val, len);
|
2022-07-01 07:24:58 +00:00
|
|
|
|
local_utility::free_memory(val);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-07 09:51:09 +00:00
|
|
|
|
SET_OPT_ID(is_multiout, IS_MULTI_OUT, extension_none)
|
|
|
|
|
else SET_OPT_ID(multiout_type, MULTI_OUT_TYPE, extension_multiout_type)
|
|
|
|
|
else SET_OPT_ID(color_mode, COLOR_MODE, extension_color_mode)
|
|
|
|
|
else SET_OPT_ID(erase_color, FILTER, extension_erase_color)
|
|
|
|
|
else SET_OPT_ID(erase_multiout_red, RID_MULTIOUT_RED, extension_none)
|
|
|
|
|
else SET_OPT_ID(erase_paper_red, RID_ANSWER_SHEET_RED, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_background, ERASE_BACKGROUND, extension_none)
|
|
|
|
|
else SET_OPT_ID(background_color_range, BKG_COLOR_RANGE, extension_none)
|
|
|
|
|
else SET_OPT_ID(sharpen, SHARPEN, extension_sharpen)
|
|
|
|
|
else SET_OPT_ID(erase_morr, RID_MORR, extension_none)
|
|
|
|
|
else SET_OPT_ID(erase_grids, RID_GRID, extension_none)
|
|
|
|
|
else SET_OPT_ID(error_extend, ERROR_EXTENSION, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_noise_modify, NOISE_OPTIMIZE, extension_none)
|
|
|
|
|
else SET_OPT_ID(noise_threshold, NOISE_SIZE, extension_none)
|
|
|
|
|
else SET_OPT_ID(paper, PAPER, extension_paper)
|
|
|
|
|
else SET_OPT_ID(is_custom_area, CUSTOM_AREA, extension_none)
|
|
|
|
|
else SET_OPT_ID(curstom_area_l, CUSTOM_AREA_LEFT, extension_none)
|
|
|
|
|
else SET_OPT_ID(curstom_area_r, CUSTOM_AREA_RIGHT, extension_none)
|
|
|
|
|
else SET_OPT_ID(curstom_area_t, CUSTOM_AREA_TOP, extension_none)
|
|
|
|
|
else SET_OPT_ID(curstom_area_b, CUSTOM_AREA_BOTTOM, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_size_check, SIZE_CHECK, extension_none)
|
|
|
|
|
else SET_OPT_ID(page, PAGE, extension_page)
|
|
|
|
|
else SET_OPT_ID(blank_page_threshold, DISCARD_BLANK_SENS, extension_none)
|
|
|
|
|
else SET_OPT_ID(resolution, RESOLUTION, extension_none)
|
|
|
|
|
else SET_OPT_ID(image_quality, IMAGE_QUALITY, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_swap, EXCHANGE, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_split, SPLIT, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_auto_deskew, ANTI_SKEW, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_custom_gamma, IS_CUSTOM_GAMMA, extension_none)
|
|
|
|
|
else SET_OPT_ID(bright, BRIGHTNESS, extension_none)
|
|
|
|
|
else SET_OPT_ID(contrast, CONTRAST, extension_none)
|
|
|
|
|
else SET_OPT_ID(gamma, GAMMA, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_black_frame, ERASE_BLACK_FRAME, extension_none)
|
|
|
|
|
else SET_OPT_ID(deep_sample, DARK_SAMPLE, extension_none)
|
|
|
|
|
else SET_OPT_ID(threshold, THRESHOLD, extension_none)
|
|
|
|
|
else SET_OPT_ID(anti_noise, ANTI_NOISE_LEVEL, extension_none)
|
|
|
|
|
else SET_OPT_ID(margin, MARGIN, extension_none)
|
|
|
|
|
else SET_OPT_ID(fill_background, FILL_BKG_MODE, extension_fill_bkg_method)
|
|
|
|
|
else SET_OPT_ID(is_anti_permeate, IS_ANTI_PERMEATE, extension_none)
|
|
|
|
|
else SET_OPT_ID(anti_permeate_level, ANTI_PERMEATE_LEVEL, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_hole, RID_HOLE, extension_none)
|
|
|
|
|
else SET_OPT_ID(search_hole_range, SEARCH_HOLE_RANGE, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_filling_color, IS_FILL_COLOR, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_ultrasonic_check, IS_ULTROSONIC_CHECK, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_check_staple, IS_CHECK_STAPLE, extension_none)
|
|
|
|
|
else SET_OPT_ID(scan_mode, SCAN_MODE, extension_none)
|
|
|
|
|
else SET_OPT_ID(scan_count, SCAN_COUNT, extension_none)
|
|
|
|
|
else SET_OPT_ID(text_direction, TEXT_DIRECTION, extension_text_direction)
|
|
|
|
|
else SET_OPT_ID(is_rotate_bkg180, IS_ROTATE_BKG_180, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_check_dogear, IS_CHECK_DOG_EAR, extension_none)
|
|
|
|
|
else SET_OPT_ID(dogear_size, DOG_EAR_SIZE, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_check_skew, IS_CHECK_ASKEW, extension_none)
|
|
|
|
|
else SET_OPT_ID(skew_range, ASKEW_RANGE, extension_none)
|
|
|
|
|
else SET_OPT_ID(black_white_threshold, BINARY_THRESHOLD, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_photo_mode, IS_PHOTO_MODE, extension_none)
|
|
|
|
|
else SET_OPT_ID(double_feed_handle, DOUBLE_FEED_HANDLE, extension_none)
|
|
|
|
|
else SET_OPT_ID(scan_when_paper_on, WAIT_TO_SCAN, extension_none)
|
|
|
|
|
else SET_OPT_ID(feed_strength, FEED_STRENGTH, extension_none)
|
|
|
|
|
else SET_OPT_ID(power_scheme, TIME_TO_SLEEP, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_auto_strength, IS_AUTO_FEED_STRENGTH, extension_none)
|
|
|
|
|
else SET_OPT_ID(feed_strength_value , FEED_STRENGTH_VALUE, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_reverse_bw, REVERSE_01, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_hole_l, RID_HOLE_L, extension_none)
|
|
|
|
|
else SET_OPT_ID(search_hole_range_l, SEARCH_HOLE_RANGE_L, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_hole_r, RID_HOLE_R, extension_none)
|
|
|
|
|
else SET_OPT_ID(search_hole_range_r, SEARCH_HOLE_RANGE_R, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_hole_t, RID_HOLE_T, extension_none)
|
|
|
|
|
else SET_OPT_ID(search_hole_range_t, SEARCH_HOLE_RANGE_T, extension_none)
|
|
|
|
|
else SET_OPT_ID(is_erase_hole_b, RID_HOLE_B, extension_none)
|
|
|
|
|
else SET_OPT_ID(search_hole_range_b, SEARCH_HOLE_RANGE_B, extension_none)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
op_id++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define EX_APPENDIX_API(name) \
|
|
|
|
|
{ \
|
|
|
|
|
EXAPI ea; \
|
|
|
|
|
ea.ind = ex_##name##_id_ = ex_id_++; \
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_##name; \
|
|
|
|
|
ex_opts_.push_back(ea); \
|
|
|
|
|
}
|
|
|
|
|
EX_APPENDIX_API(final_compression);
|
|
|
|
|
EX_APPENDIX_API(final_format);
|
|
|
|
|
EX_APPENDIX_API(serial);
|
|
|
|
|
EX_APPENDIX_API(to_be_scan);
|
|
|
|
|
EX_APPENDIX_API(scan_with_hole);
|
|
|
|
|
EX_APPENDIX_API(device_code);
|
|
|
|
|
EX_APPENDIX_API(power);
|
|
|
|
|
EX_APPENDIX_API(hardware_version);
|
|
|
|
|
EX_APPENDIX_API(ip);
|
|
|
|
|
|
2022-06-28 09:17:10 +00:00
|
|
|
|
if (black_white_threshold_id_ == -1)
|
|
|
|
|
black_white_threshold_id_ = 0x8836;
|
|
|
|
|
|
2022-09-12 06:45:07 +00:00
|
|
|
|
if (is_erase_hole_id_ == -1)
|
|
|
|
|
{
|
|
|
|
|
// 兼容老的除孔算法
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = is_erase_hole_id_ = ex_id_++;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_erase_hole;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ea.ind = search_hole_range_id_ = ex_id_++;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_search_hole_range;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
2022-10-08 06:13:09 +00:00
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
int scanner::control_read_string(int code, std::string& ret)
|
|
|
|
|
{
|
|
|
|
|
char* buf = NULL;
|
|
|
|
|
unsigned len = 0;
|
|
|
|
|
int err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
|
|
|
|
|
|
|
|
|
|
ret = "";
|
|
|
|
|
if (err == SANE_STATUS_NO_MEM)
|
|
|
|
|
{
|
|
|
|
|
len += 4;
|
|
|
|
|
buf = new char[len];
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
|
|
|
|
|
if (err == SANE_STATUS_GOOD)
|
|
|
|
|
ret = buf;
|
|
|
|
|
delete[] buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void scanner::extension_none(int id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_multiout_type(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ex_multiout_type_id_ = ex_id_++;
|
|
|
|
|
ea.ind = ex_multiout_type_id_;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_multiout;
|
|
|
|
|
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_color_mode(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_color_mode_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_color_mode;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ex_auto_color_type_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ind = ex_auto_color_type_id_;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_auto_color_type;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_sharpen(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ex_sharpen_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ind = ex_sharpen_id_;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_sharpen;
|
|
|
|
|
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_paper(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_paper_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_paper;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_paper_lateral_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_paper_lateral;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_auto_paper_size_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_auto_paper_size;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_is_paper_auto_crop_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_auto_paper_crop;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_fill_bkg_method(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_fill_background_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_fill_background;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_text_direction(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_text_direction_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_text_direction;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
void scanner::extension_page(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
2022-09-23 08:47:00 +00:00
|
|
|
|
wchar_t msg[128] = { 0 };
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
ea.ind = ex_duplex_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_duplex;
|
|
|
|
|
ex_opts_.push_back(ea);
|
2022-09-23 08:47:00 +00:00
|
|
|
|
{
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"handle_ex_duplex of id: %d\r\n", ea.ind);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
ea.ind = ex_discard_blank_page_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_discard_blank_page;
|
|
|
|
|
ex_opts_.push_back(ea);
|
2022-09-23 08:47:00 +00:00
|
|
|
|
{
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"handle_ex_discard_blank_page of id: %d\r\n", ea.ind);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
ea.ind = ex_discard_blank_receipt_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_discard_blank_receipt;
|
|
|
|
|
ex_opts_.push_back(ea);
|
2022-09-23 08:47:00 +00:00
|
|
|
|
{
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"handle_ex_discard_blank_receipt of id: %d\r\n", ea.ind);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
ea.ind = ex_is_page_fold_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_page_fold;
|
|
|
|
|
ex_opts_.push_back(ea);
|
2022-09-23 08:47:00 +00:00
|
|
|
|
{
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"handle_ex_page_fold of id: %d\r\n", ea.ind);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
void scanner::extension_erase_color(int id)
|
|
|
|
|
{
|
|
|
|
|
EXAPI ea;
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_color_filter_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_color_filter;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
|
|
|
|
|
ea.ind = ex_color_enhance_id_ = ex_id_++;
|
|
|
|
|
ea.base_ind = id;
|
|
|
|
|
ea.ex_api = &scanner::handle_ex_color_enhance;
|
|
|
|
|
ex_opts_.push_back(ea);
|
|
|
|
|
}
|
|
|
|
|
bool scanner::get_option_value_with_parent(int sn, set_opt_value setv, void* param) // return true if handled
|
|
|
|
|
{
|
|
|
|
|
bool handled = true;
|
|
|
|
|
|
|
|
|
|
if (sn == scan_count_id_)
|
|
|
|
|
{
|
|
|
|
|
SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
|
|
|
|
|
char* buf = new char[parent->size + 4];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, parent->size);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, buf);
|
|
|
|
|
handled = compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf);
|
|
|
|
|
delete[] buf;
|
|
|
|
|
if (handled)
|
|
|
|
|
{
|
|
|
|
|
int count = -1;
|
|
|
|
|
value_role role = VAL_ROLE_CURRENT;
|
|
|
|
|
buf = (char*)hg_sane_middleware::instance()->get_def_value(handle_, scan_mode_id_);
|
|
|
|
|
if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf))
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
local_utility::free_memory(buf);
|
|
|
|
|
|
|
|
|
|
setv(&count, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), param);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
handled = false;
|
|
|
|
|
|
|
|
|
|
return handled;
|
|
|
|
|
}
|
|
|
|
|
bool scanner::set_option_value_with_parent(int sn, void* data, int* err) // return true if handled
|
|
|
|
|
{
|
|
|
|
|
bool handled = true;
|
|
|
|
|
|
|
|
|
|
if (sn == scan_count_id_)
|
|
|
|
|
{
|
|
|
|
|
SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
|
|
|
|
|
char* val = new char[parent->size + 4];
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
memset(val, 0, parent->size + 4);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, val);
|
|
|
|
|
if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, val))
|
|
|
|
|
{
|
|
|
|
|
if (*(int*)data != -1)
|
|
|
|
|
{
|
|
|
|
|
strcpy(val, OPTION_VALUE_SMZS_SMZDZS);
|
|
|
|
|
*err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (*(int*)data == -1)
|
|
|
|
|
{
|
|
|
|
|
strcpy(val, OPTION_VALUE_SMZS_LXSM);
|
|
|
|
|
*err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
}
|
|
|
|
|
handled = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
handled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handled;
|
|
|
|
|
}
|
|
|
|
|
int scanner::set_option_value(int sn, SANE_Value_Type type, int size, void* data)
|
|
|
|
|
{
|
|
|
|
|
char* buf = NULL;
|
|
|
|
|
SANE_Bool sb = SANE_FALSE;
|
|
|
|
|
SANE_Int si = 0, after = 0;
|
|
|
|
|
SANE_Fixed sf = 0;
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
void* val = data;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
if (type == SANE_TYPE_BOOL)
|
|
|
|
|
{
|
|
|
|
|
sb = *(bool*)data ? SANE_TRUE : SANE_FALSE;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
val = &sb;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
else if (type == SANE_TYPE_INT)
|
|
|
|
|
{
|
|
|
|
|
si = *(int*)data;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
val = &si;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
else if (type == SANE_TYPE_FIXED)
|
|
|
|
|
{
|
|
|
|
|
sf = SANE_FIX(*(float*)data);
|
2022-06-16 08:04:58 +00:00
|
|
|
|
val = &sf;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
buf = new char[size + 4];
|
|
|
|
|
memset(buf, 0, size + 4);
|
2022-06-15 09:07:51 +00:00
|
|
|
|
strcpy(buf, ((std::string*)data)->c_str());
|
2022-06-16 08:04:58 +00:00
|
|
|
|
val = buf;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-16 08:04:58 +00:00
|
|
|
|
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, sn, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
|
|
|
|
|
if (type == SANE_TYPE_BOOL)
|
|
|
|
|
{
|
|
|
|
|
*(bool*)data = sb == SANE_TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (type == SANE_TYPE_INT)
|
|
|
|
|
{
|
|
|
|
|
*(int*)data = si;
|
|
|
|
|
}
|
|
|
|
|
else if (type == SANE_TYPE_FIXED)
|
|
|
|
|
{
|
2022-07-18 02:55:01 +00:00
|
|
|
|
*(float*)data = (float)SANE_UNFIX(sf);
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
else if(buf)
|
|
|
|
|
{
|
|
|
|
|
strcpy((char*)val, buf);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
delete[] buf;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scanner::EXAPIPOS scanner::find_ex_api(int op_id)
|
|
|
|
|
{
|
|
|
|
|
return std::find(ex_opts_.begin(), ex_opts_.end(), op_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(multiout)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
char* cur = new char[desc->size],
|
|
|
|
|
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
|
|
|
|
|
init = sane_opt_trans::multiout_value_to_twain(def),
|
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
|
|
local_utility::free_memory(def);
|
|
|
|
|
memset(cur, 0, desc->size);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
|
|
|
|
|
now = sane_opt_trans::multiout_value_to_twain(cur);
|
|
|
|
|
delete[] cur;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// parent item ...
|
|
|
|
|
SANE_Bool enable = SANE_TRUE;
|
|
|
|
|
if (hg_sane_middleware::instance()->get_cur_value(handle_, is_multiout_id_, &enable))
|
|
|
|
|
{
|
|
|
|
|
if (!enable)
|
|
|
|
|
now = MULTI_OUT_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
// we have no 'MULTI_OUT_NONE' item in this option, this is used as is_multiout_id_
|
|
|
|
|
val = MULTI_OUT_NONE;
|
|
|
|
|
value_role role = val == now ? VAL_ROLE_CURRENT : VAL_ROLE_NONE;
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
val = sane_opt_trans::multiout_value_to_twain(desc->constraint.string_list[i]);
|
|
|
|
|
if (val == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (val == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<int>(now, init, setv, data);
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* val = new char[desc->size];
|
|
|
|
|
const char* in = sane_opt_trans::multiout_value_from_twain(*(int*)data);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
if (in && strcmp(in, "\346\227\240"))
|
|
|
|
|
{
|
|
|
|
|
// enable multi-out ...
|
|
|
|
|
*((SANE_Bool*)val) = SANE_TRUE;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, is_multiout_id_, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
strcpy(val, in);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// disable multi-out, let multiout type side
|
|
|
|
|
base_id = is_multiout_id_;
|
|
|
|
|
*((SANE_Bool*)val) = SANE_FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
delete[] val;
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(auto_color_type)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
len = sane_opt_trans::auto_color_type_to_twain(buf);
|
|
|
|
|
setv(&len, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, sane_opt_trans::auto_color_type_from_twain(*(int*)data));
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(color_mode)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
char* cur = new char[desc->size],
|
|
|
|
|
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
|
|
|
|
|
init = sane_opt_trans::color_mode_to_twain(def),
|
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
|
|
local_utility::free_memory(def);
|
|
|
|
|
memset(cur, 0, desc->size);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
|
|
|
|
|
now = sane_opt_trans::color_mode_to_twain(cur);
|
|
|
|
|
delete[] cur;
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
val = sane_opt_trans::color_mode_to_twain(desc->constraint.string_list[i]);
|
|
|
|
|
if (val == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (val == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<int>(now, init, setv, data);
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* val = new char[desc->size];
|
|
|
|
|
const char* in = sane_opt_trans::color_mode_from_twain(*(int*)data);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
strcpy(val, in);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
delete[] val;
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(sharpen)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
char* cur = new char[desc->size],
|
|
|
|
|
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
|
|
|
|
|
init = sane_opt_trans::sharpen_to_twain(def),
|
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
|
|
local_utility::free_memory(def);
|
|
|
|
|
memset(cur, 0, desc->size);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
|
|
|
|
|
now = sane_opt_trans::sharpen_to_twain(cur);
|
|
|
|
|
delete[] cur;
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
val = sane_opt_trans::sharpen_to_twain(desc->constraint.string_list[i]);
|
|
|
|
|
if (val == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (val == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<int>(now, init, setv, data);
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* val = new char[desc->size];
|
|
|
|
|
const char* in = sane_opt_trans::sharpen_from_twain(*(int*)data);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
|
|
|
|
|
delete[] val;
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(paper)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
int now = sane_opt_trans::paper_to_twain(buf),
|
|
|
|
|
init = sane_opt_trans::paper_to_twain(def),
|
|
|
|
|
val = 0;
|
2022-09-26 09:31:57 +00:00
|
|
|
|
|
|
|
|
|
local_utility::free_memory(def);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
val = sane_opt_trans::paper_to_twain(desc->constraint.string_list[i]);
|
|
|
|
|
if (val == -1)
|
|
|
|
|
continue;
|
|
|
|
|
if (val == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (val == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<int>(now, init, setv, data);
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else if (sane_opt_trans::paper_from_twain(*(int*)data))
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
strcpy(buf, sane_opt_trans::paper_from_twain(*(int*)data));
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ret = SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(paper_lateral)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
const char* lateral_swap = NULL;
|
|
|
|
|
bool lateral = false;
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
lateral_swap = sane_opt_trans::switch_paper_lateral(buf);
|
|
|
|
|
lateral = sane_opt_trans::is_paper_lateral(buf);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
setv(&lateral, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else if (lateral_swap)
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
if (lateral != *(bool*)data)
|
|
|
|
|
{
|
|
|
|
|
strcpy(buf, lateral_swap);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-10-07 09:51:09 +00:00
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
if (*(bool*)data)
|
|
|
|
|
{
|
|
|
|
|
// set to A4Lateral ...
|
|
|
|
|
strcpy(buf, OPTION_VALUE_ZZCC_A4HX);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
//ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(auto_paper_size)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
bool yes = strcmp(buf, OPTION_VALUE_ZZCC_PPYSCC) == 0;
|
|
|
|
|
setv(&yes, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_PPYSCC : OPTION_VALUE_ZZCC_A4);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(auto_paper_crop)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
bool yes = strcmp(buf, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0;
|
|
|
|
|
setv(&yes, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_ZDSMCCZDCQ : OPTION_VALUE_ZZCC_ZDSMCC);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(text_direction)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
int len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
float now = .0f, init = sane_opt_trans::text_direction_to_twain(def), val = .0f;
|
|
|
|
|
|
|
|
|
|
local_utility::free_memory(def);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
now = sane_opt_trans::text_direction_to_twain(buf);
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
val = sane_opt_trans::text_direction_to_twain(desc->constraint.string_list[i]);
|
|
|
|
|
if (IS_DOUBLE_EQUAL(val, now))
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (IS_DOUBLE_EQUAL(val, init))
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&val, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<float>(now, init, setv, data);
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, sane_opt_trans::text_direction_from_twain(*(float*)data));
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(duplex)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
bool val = *(bool*)data;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
unsigned len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
void* init = hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
|
|
|
|
|
if (val && strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0 ||
|
|
|
|
|
!val && strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
|
|
|
|
|
setv(&val, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), data);
|
|
|
|
|
else if (setv(&val, VAL_ROLE_CURRENT, data))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0)
|
|
|
|
|
{
|
|
|
|
|
val = true;
|
|
|
|
|
setv(&val, VAL_ROLE_DEFAULT, data);
|
|
|
|
|
}
|
|
|
|
|
if (strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
|
|
|
|
|
{
|
|
|
|
|
val = false;
|
|
|
|
|
setv(&val, VAL_ROLE_DEFAULT, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-26 09:31:57 +00:00
|
|
|
|
local_utility::free_memory(init);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy(buf, val ? OPTION_VALUE_SMYM_SM : OPTION_VALUE_SMYM_DM);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(fill_background)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
bool val = *(bool*)data;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
unsigned len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
|
|
|
|
|
set_cur_and_def_value<bool>(strcmp(buf, OPTION_VALUE_BJTCFS_TDBX) == 0, strcmp(init, OPTION_VALUE_BJTCFS_TDBX) == 0, setv, data);
|
|
|
|
|
local_utility::free_memory(init);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy(buf, val ? OPTION_VALUE_BJTCFS_TDBX : OPTION_VALUE_BJTCFS_ADBX);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(discard_blank_page)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
bool val = *(bool*)data;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
unsigned len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYTY) == 0;
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (val)
|
|
|
|
|
strcpy(buf, OPTION_VALUE_SMYM_TGKBYTY);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
strcpy(buf, init);
|
|
|
|
|
local_utility::free_memory(init);
|
|
|
|
|
}
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(discard_blank_receipt)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
bool val = *(bool*)data;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
unsigned len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYFPZ) == 0;
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (val)
|
|
|
|
|
strcpy(buf, OPTION_VALUE_SMYM_TGKBYFPZ);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
strcpy(buf, init);
|
|
|
|
|
local_utility::free_memory(init);
|
|
|
|
|
}
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(page_fold)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
bool val = *(bool*)data;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
unsigned len = desc->size + 4;
|
|
|
|
|
char* buf = new char[len];
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
val = strcmp(buf, OPTION_VALUE_SMYM_DZ) == 0;
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (val)
|
|
|
|
|
strcpy(buf, OPTION_VALUE_SMYM_DZ);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
|
|
|
|
|
strcpy(buf, init);
|
|
|
|
|
local_utility::free_memory(init);
|
|
|
|
|
}
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(color_filter) // int (filter_value)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
char* buf = NULL;
|
|
|
|
|
unsigned int len = 0;
|
|
|
|
|
|
|
|
|
|
if (desc)
|
|
|
|
|
{
|
|
|
|
|
len = desc->size + 4;
|
|
|
|
|
buf = new char[len];
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
bool filter = false;
|
|
|
|
|
int val = FILTER_NONE, now = FILTER_NONE;
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
|
|
|
|
|
if (!filter)
|
|
|
|
|
now = val;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
|
|
|
|
|
if (!filter && v != FILTER_NONE)
|
|
|
|
|
continue;
|
|
|
|
|
if (v == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (v == val)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&v, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), true);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, val);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(color_enhance) // int (enhance_value)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
|
|
|
|
|
char* buf = NULL;
|
|
|
|
|
unsigned int len = 0;
|
|
|
|
|
|
|
|
|
|
if (desc)
|
|
|
|
|
{
|
|
|
|
|
len = desc->size + 4;
|
|
|
|
|
buf = new char[len];
|
|
|
|
|
memset(buf, 0, len);
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
bool filter = false;
|
|
|
|
|
int val = ENHANCE_NONE, now = ENHANCE_NONE;
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
|
|
|
|
|
now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
|
|
|
|
|
if (filter)
|
|
|
|
|
now = val;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
|
|
|
|
|
if (filter && v != ENHANCE_NONE)
|
|
|
|
|
continue;
|
|
|
|
|
if (v == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (v == val)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&v, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), false);
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, val);
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
delete[] buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(final_compression)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
int* compression = (int*)data;
|
|
|
|
|
unsigned int len = sizeof(*compression);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
int val = 0;
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_COMPRESSION, &val, &len);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
int i = SANE_COMPRESSION_FIRST;
|
|
|
|
|
for (; i < SANE_COMPRESSION_LAST; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
if (i == val)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (i == SANE_COMPRESSION_NONE)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
int v = sane_opt_trans::compression_to_twain(i);
|
|
|
|
|
if (!setv(&v, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int val = sane_opt_trans::compression_from_twain(*(int*)data);
|
|
|
|
|
len = sizeof(val);
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_COMPRESSION, &val, &len);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(final_format)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_FinalImgFormat ff;
|
|
|
|
|
unsigned int len = sizeof(ff);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &ff, &len);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
int now = ff.img_format, init = SANE_IMAGE_TYPE_BMP;
|
|
|
|
|
std::vector<int> all(sane_opt_trans::support_image_types());
|
2022-07-18 02:55:01 +00:00
|
|
|
|
for (int i = 0; i < (int)all.size(); ++i)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
ff.img_format = (SANE_ImageType)all[i];
|
|
|
|
|
if (ff.img_format == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (ff.img_format == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
if (!setv(&ff, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_IMAGE_FORMAT, data, &len);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(serial)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
std::string val("");
|
|
|
|
|
|
|
|
|
|
ret = control_read_string(IO_CTRL_CODE_GET_SERIAL, val);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(to_be_scan)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Bool wait_paper = SANE_FALSE;
|
|
|
|
|
unsigned int len = sizeof(wait_paper);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
bool val = wait_paper == SANE_TRUE;
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
wait_paper = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(scan_with_hole)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
SANE_Bool with_hole = SANE_FALSE;
|
|
|
|
|
unsigned int len = sizeof(with_hole);
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WITH_HOLE, &with_hole, &len);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
bool val = with_hole == SANE_TRUE;
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
with_hole = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WITH_HOLE, &with_hole, &len);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(device_code)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
std::string val("");
|
|
|
|
|
|
|
|
|
|
ret = control_read_string(IO_CTRL_CODE_GET_DEVICE_CODE, val);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(power)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
SANE_Power now = SANE_POWER_MINUTES_30, init = SANE_POWER_MINUTES_30;
|
|
|
|
|
unsigned int len = sizeof(now);
|
|
|
|
|
|
|
|
|
|
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_POWER_LEVEL, &now, &len);
|
|
|
|
|
for (int i = SANE_POWER_FIRST; i < SANE_POWER_LAST; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
if (i == now)
|
|
|
|
|
role = VAL_ROLE_CURRENT;
|
|
|
|
|
if (i == init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
|
|
|
|
|
SANE_Power power = (SANE_Power)i;
|
|
|
|
|
if (!setv(&power, role, data))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SANE_Power power = *((SANE_Power*)data);
|
|
|
|
|
unsigned int len = sizeof(power);
|
|
|
|
|
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_POWER_LEVEL, &power, &len);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(hardware_version)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
std::string val("");
|
|
|
|
|
|
|
|
|
|
ret = control_read_string(IO_CTRL_CODE_GET_HARDWARE_VERSION, val);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(ip)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
std::string val("");
|
|
|
|
|
|
|
|
|
|
ret = control_read_string(IO_CTRL_CODE_GET_IP, val);
|
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
setv(&val, VAL_ROLE_CURRENT, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-09-12 06:45:07 +00:00
|
|
|
|
EX_OPTION_HANDLER_IMPL(erase_hole)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
if (is_erase_hole_l_id_ != -1 || is_erase_hole_r_id_ != -1)
|
|
|
|
|
{
|
|
|
|
|
SANE_Bool yes = SANE_FALSE;
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
if (is_erase_hole_l_id_ != -1)
|
|
|
|
|
hg_sane_middleware::instance()->set_option(handle_, is_erase_hole_l_id_, SANE_ACTION_GET_VALUE, &yes, &after);
|
|
|
|
|
if (!yes && is_erase_hole_r_id_ != -1)
|
|
|
|
|
hg_sane_middleware::instance()->set_option(handle_, is_erase_hole_r_id_, SANE_ACTION_GET_VALUE, &yes, &after);
|
|
|
|
|
|
|
|
|
|
bool v = yes == SANE_TRUE;
|
|
|
|
|
setv(&v, VAL_ROLE_CURRENT, data);
|
|
|
|
|
ret = SCANNER_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
yes = *(bool*)data ? SANE_TRUE : SANE_FALSE;
|
|
|
|
|
if (is_erase_hole_l_id_ != -1)
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, is_erase_hole_l_id_, SANE_ACTION_SET_VALUE, &yes, &after);
|
|
|
|
|
yes = *(bool*)data ? SANE_TRUE : SANE_FALSE;
|
|
|
|
|
if (is_erase_hole_r_id_ != -1)
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, is_erase_hole_r_id_, SANE_ACTION_SET_VALUE, &yes, &after);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
EX_OPTION_HANDLER_IMPL(search_hole_range)
|
|
|
|
|
{
|
|
|
|
|
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
if (search_hole_range_l_id_ != -1 || search_hole_range_r_id_ != -1)
|
|
|
|
|
{
|
|
|
|
|
SANE_Fixed val = 0;
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
double rv = .0f;
|
|
|
|
|
if (setv)
|
|
|
|
|
{
|
|
|
|
|
if (search_hole_range_l_id_ != -1)
|
|
|
|
|
hg_sane_middleware::instance()->set_option(handle_, search_hole_range_l_id_, SANE_ACTION_GET_VALUE, &val, &after);
|
|
|
|
|
rv = SANE_UNFIX(val);
|
|
|
|
|
if (search_hole_range_r_id_ != -1)
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->set_option(handle_, search_hole_range_r_id_, SANE_ACTION_GET_VALUE, &val, &after);
|
|
|
|
|
if (rv < SANE_UNFIX(val))
|
|
|
|
|
rv = SANE_UNFIX(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setv(&rv, VAL_ROLE_CURRENT, data);
|
|
|
|
|
ret = SCANNER_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
val = SANE_FIX(*(double*)data);
|
|
|
|
|
if (search_hole_range_l_id_ != -1)
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, search_hole_range_l_id_, SANE_ACTION_SET_VALUE, &val, &after);
|
|
|
|
|
val = SANE_FIX(*(double*)data);
|
|
|
|
|
if (search_hole_range_r_id_ != -1)
|
|
|
|
|
ret = hg_sane_middleware::instance()->set_option(handle_, search_hole_range_r_id_, SANE_ACTION_SET_VALUE, &val, &after);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
// ISaneInvoker
|
|
|
|
|
COM_API_IMPLEMENT(scanner, int, start(void))
|
|
|
|
|
{
|
2022-06-18 08:48:41 +00:00
|
|
|
|
int ret = SANE_STATUS_GOOD;
|
|
|
|
|
|
2022-09-19 06:16:34 +00:00
|
|
|
|
events_.clear();
|
|
|
|
|
images_.clear();
|
2022-06-18 08:48:41 +00:00
|
|
|
|
scan_msg_ = "OK";
|
|
|
|
|
scan_err_ = false;
|
2022-07-02 09:27:21 +00:00
|
|
|
|
ret = hg_sane_middleware::instance()->start(handle_, NULL);
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
// the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ...
|
|
|
|
|
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
|
|
|
|
|
ret = hg_sane_middleware::instance()->start(handle_, NULL);
|
|
|
|
|
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (ret == SANE_STATUS_GOOD)
|
|
|
|
|
{
|
2022-07-04 08:31:37 +00:00
|
|
|
|
if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
|
|
|
|
|
indicator_->show(true);
|
|
|
|
|
|
2022-06-17 03:50:18 +00:00
|
|
|
|
unsigned int l = sizeof(img_fmt_);
|
2022-06-29 08:13:05 +00:00
|
|
|
|
SANE_CompressionType cmprsn = img_fmt_.compress.compression;
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l))
|
|
|
|
|
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
2022-06-29 08:13:05 +00:00
|
|
|
|
img_fmt_.compress.compression = cmprsn;
|
2022-06-17 03:50:18 +00:00
|
|
|
|
}
|
2022-09-22 08:25:03 +00:00
|
|
|
|
//else if (indicator_.get())
|
|
|
|
|
//{
|
|
|
|
|
// indicator_->notify_scan_over(hg_scanner_err_description(ret), true);
|
|
|
|
|
//}
|
|
|
|
|
else
|
2022-07-04 08:31:37 +00:00
|
|
|
|
{
|
2022-09-22 08:25:03 +00:00
|
|
|
|
std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8));
|
2022-09-28 12:01:14 +00:00
|
|
|
|
HWND parent = setting_.get() ? setting_->hwnd() : NULL;
|
2022-09-22 08:25:03 +00:00
|
|
|
|
if (indicator_.get())
|
2022-09-28 12:01:14 +00:00
|
|
|
|
indicator_->show(false);
|
|
|
|
|
MessageBoxW(parent, msg.c_str(), L"\u542F\u52A8\u5931\u8D25", MB_OK | MB_ICONERROR);
|
2022-07-04 08:31:37 +00:00
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
prev_start_result_ = ret;
|
2022-09-19 06:16:34 +00:00
|
|
|
|
is_scanning_ = ret == SANE_STATUS_GOOD;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
return local_utility::sane_statu_2_scanner_err(ret);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, int, stop(void))
|
|
|
|
|
{
|
|
|
|
|
return hg_sane_middleware::instance()->stop(handle_);
|
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, int, get_event(void))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
return events_.take();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
|
|
|
|
|
{
|
|
|
|
|
int count = get_scanned_images(milliseconds);
|
|
|
|
|
|
|
|
|
|
return count > 0;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
|
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
size_t count = images_.count();
|
2022-07-02 09:27:21 +00:00
|
|
|
|
DWORD elapse = 10;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-09-19 06:16:34 +00:00
|
|
|
|
is_ui_wait_img_ = true;
|
|
|
|
|
while (is_scanning_ && count == 0 && milliseconds)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-18 08:48:41 +00:00
|
|
|
|
MSG msg = { 0 };
|
|
|
|
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
|
|
|
{
|
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
|
DispatchMessageW(&msg);
|
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
Sleep(elapse);
|
|
|
|
|
|
|
|
|
|
int ev = get_event();
|
|
|
|
|
|
|
|
|
|
count = images_.count();
|
|
|
|
|
if (ev == SANE_EVENT_SCAN_FINISHED)
|
2022-06-18 08:48:41 +00:00
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
ui_hide();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (ev == SANE_EVENT_UI_CLOSE_CANCEL)
|
|
|
|
|
{
|
|
|
|
|
stop();
|
|
|
|
|
ui_hide();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (ev == SANE_EVENT_UI_CLOSE_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
ui_hide();
|
|
|
|
|
break;
|
2022-06-18 08:48:41 +00:00
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
if (milliseconds != -1)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
if (milliseconds <= elapse)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2022-07-02 09:27:21 +00:00
|
|
|
|
milliseconds -= elapse;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-19 06:16:34 +00:00
|
|
|
|
is_ui_wait_img_ = false;
|
|
|
|
|
count = images_.count();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
wchar_t msg[128] = { 0 };
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"Wait image count = %d\r\n", count);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
2022-06-16 09:28:46 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
scanned_img* img = images_.take();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
return dynamic_cast<IScanImg*>(img);
|
|
|
|
|
}
|
2022-06-29 08:13:05 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header, size_t* bytes))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-29 08:13:05 +00:00
|
|
|
|
return images_.get_header(header, bytes);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, is_online(void))
|
|
|
|
|
{
|
|
|
|
|
return !scanner::get_scanner_name(id_).empty();
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, is_paper_on(void))
|
|
|
|
|
{
|
|
|
|
|
SANE_Bool on = SANE_FALSE;
|
|
|
|
|
unsigned int len = sizeof(on);
|
|
|
|
|
|
|
|
|
|
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_PAPER_ON, &on, &len) == SANE_STATUS_GOOD)
|
|
|
|
|
return on == SANE_TRUE;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes))
|
|
|
|
|
{
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
if (desc)
|
|
|
|
|
{
|
|
|
|
|
if (type)
|
|
|
|
|
*type = scanner::from_sane_type(desc->type);
|
|
|
|
|
if (limit)
|
|
|
|
|
*limit = scanner::from_sane_constraint(desc->constraint_type);
|
|
|
|
|
if (bytes)
|
|
|
|
|
*bytes = desc->size;
|
|
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* param))
|
|
|
|
|
{
|
|
|
|
|
EXAPIPOS ex = find_ex_api(sn);
|
|
|
|
|
int ret = SANE_STATUS_INVAL;
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
|
|
|
|
|
if (ex == ex_opts_.end())
|
|
|
|
|
{
|
|
|
|
|
if (get_option_value_with_parent(sn, setval, param))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
|
|
|
|
|
void* init = hg_sane_middleware::instance()->get_def_value(handle_, sn);
|
|
|
|
|
ret = SANE_STATUS_GOOD;
|
|
|
|
|
if (desc->type == SANE_TYPE_BOOL)
|
|
|
|
|
{
|
|
|
|
|
SANE_Bool v = SANE_FALSE;
|
|
|
|
|
bool val = false;
|
|
|
|
|
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &v);
|
|
|
|
|
val = v == SANE_TRUE;
|
|
|
|
|
set_cur_and_def_value<bool>(val, *(SANE_Bool*)init == SANE_TRUE, setval, param);
|
|
|
|
|
}
|
|
|
|
|
else if (desc->type == SANE_TYPE_INT)
|
|
|
|
|
{
|
|
|
|
|
SANE_Int cur = 0, def = *(SANE_Int*)init;
|
|
|
|
|
int val = 0;
|
|
|
|
|
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
|
|
|
|
|
val = cur;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
if (sn == resolution_id_)
|
|
|
|
|
dpi_ = cur;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
|
|
|
|
|
{
|
|
|
|
|
set_value_range<SANE_Int, int>(cur, def, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setval, param, scanner::to_int);
|
|
|
|
|
}
|
|
|
|
|
else if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
|
|
|
|
|
{
|
|
|
|
|
const SANE_Word* v = desc->constraint.word_list;
|
|
|
|
|
for (int i = 0; i < v[0]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
if (v[i + 1] == cur)
|
|
|
|
|
role = value_role(role | VAL_ROLE_CURRENT);
|
|
|
|
|
if (v[i + 1] == *(SANE_Int*)init)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
val = v[i + 1];
|
|
|
|
|
if (!setval(&val, role, param))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<int>(val, *(SANE_Int*)init, setval, param);
|
|
|
|
|
|
|
|
|
|
}while (0);
|
|
|
|
|
}
|
|
|
|
|
else if (desc->type == SANE_TYPE_FIXED)
|
|
|
|
|
{
|
|
|
|
|
SANE_Fixed cur = 0, def = *(SANE_Fixed*)init;
|
|
|
|
|
float val = .0f;
|
|
|
|
|
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
|
2022-06-16 08:04:58 +00:00
|
|
|
|
if (sn == resolution_id_)
|
2022-07-18 02:55:01 +00:00
|
|
|
|
dpi_ = (int)(SANE_UNFIX(cur) + .5f);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
|
|
|
|
|
{
|
|
|
|
|
set_value_range<SANE_Fixed, float>(cur, def, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setval, param, scanner::to_float);
|
|
|
|
|
}
|
|
|
|
|
else if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
|
|
|
|
|
{
|
|
|
|
|
const SANE_Word* v = desc->constraint.word_list;
|
|
|
|
|
for (int i = 0; i < v[0]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
if (v[i + 1] == cur)
|
|
|
|
|
role = value_role(role | VAL_ROLE_CURRENT);
|
|
|
|
|
if (v[i + 1] == def)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
2022-07-18 02:55:01 +00:00
|
|
|
|
val = (float)SANE_UNFIX(v[i + 1]);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
if (!setval(&val, role, param))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-07-18 02:55:01 +00:00
|
|
|
|
set_cur_and_def_value<float>(val, (float)SANE_UNFIX(*(SANE_Fixed*)init), setval, param);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
} while (0);
|
|
|
|
|
}
|
|
|
|
|
else if (desc->type == SANE_TYPE_STRING)
|
|
|
|
|
{
|
|
|
|
|
char* buf = new char[desc->size + 4];
|
|
|
|
|
std::string val(""), def((char*)init);
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, desc->size + 4);
|
|
|
|
|
hg_sane_middleware::instance()->get_cur_value(handle_, sn, buf);
|
|
|
|
|
val = buf;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; desc->constraint.string_list[i]; ++i)
|
|
|
|
|
{
|
|
|
|
|
value_role role = VAL_ROLE_NONE;
|
|
|
|
|
if (strcmp(desc->constraint.string_list[i], buf) == 0)
|
|
|
|
|
role = value_role(role | VAL_ROLE_CURRENT);
|
|
|
|
|
if (strcmp(desc->constraint.string_list[i], (char*)init) == 0)
|
|
|
|
|
role = value_role(role | VAL_ROLE_DEFAULT);
|
|
|
|
|
|
|
|
|
|
val = desc->constraint.string_list[i];
|
|
|
|
|
if (!setval(&val, role, param))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_cur_and_def_value<std::string>(val, def, setval, param);
|
|
|
|
|
} while (0);
|
|
|
|
|
delete[] buf;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = SANE_STATUS_INVAL;
|
|
|
|
|
}
|
|
|
|
|
local_utility::free_memory(init);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = (this->*ex->ex_api)(ex->base_ind, param, setval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret == SANE_STATUS_GOOD;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val))
|
|
|
|
|
{
|
|
|
|
|
EXAPIPOS ex = find_ex_api(sn);
|
|
|
|
|
int ret = SANE_STATUS_INVAL;
|
|
|
|
|
SANE_Int after = 0;
|
|
|
|
|
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
|
|
|
|
|
|
2022-09-23 08:47:00 +00:00
|
|
|
|
{
|
|
|
|
|
wchar_t msg[128] = { 0 };
|
2022-10-07 09:51:09 +00:00
|
|
|
|
if (ex == ex_opts_.end())
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"set_value of ID: %d\r\n", sn);
|
|
|
|
|
else
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"set_value of ID: %d (base id = %d)\r\n", sn, ex->base_ind);
|
2022-09-23 08:47:00 +00:00
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
if (ex == ex_opts_.end())
|
|
|
|
|
{
|
|
|
|
|
if (!set_option_value_with_parent(sn, val, &ret))
|
|
|
|
|
ret = set_option_value(sn, desc->type, desc->size, val);
|
|
|
|
|
ret = local_utility::sane_statu_2_scanner_err(ret);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = (this->*ex->ex_api)(ex->base_ind, val, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
if (sn == resolution_id_)
|
|
|
|
|
{
|
|
|
|
|
if (desc->type == SANE_TYPE_FIXED)
|
2022-07-18 02:55:01 +00:00
|
|
|
|
dpi_ = (int)(*(float*)val + .5f);
|
2022-06-16 08:04:58 +00:00
|
|
|
|
else
|
|
|
|
|
dpi_ = *(int*)val;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-06-28 09:17:10 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, int, convert_image(SANE_ImageFormatConvert* conv))
|
|
|
|
|
{
|
|
|
|
|
return hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_CONVERT_IMAGE_FORMAT, conv, NULL);
|
|
|
|
|
}
|
2022-06-29 08:13:05 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, void, free_buffer(void* buf, int len))
|
|
|
|
|
{
|
|
|
|
|
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_FREE_MEMORY, buf, (unsigned int*)&len);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
// SANE options ID ...
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_multiout)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(multiout_type)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(color_mode)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(erase_color)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(erase_multiout_red)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(erase_paper_red)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_background)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(background_color_range)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(sharpen)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(erase_morr)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(erase_grids)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(error_extend)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_noise_modify)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(noise_threshold)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(paper)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_custom_area)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(curstom_area_l)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(curstom_area_r)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(curstom_area_t)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(curstom_area_b)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_size_check)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(page)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(blank_page_threshold)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(resolution)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(image_quality)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_swap)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_split)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_auto_deskew)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_custom_gamma)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(bright)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(contrast)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(gamma)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_black_frame)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(deep_sample)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(threshold)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(anti_noise)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(margin)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(fill_background)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_anti_permeate)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(anti_permeate_level)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_hole)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(search_hole_range)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_filling_color)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_ultrasonic_check)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_check_staple)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(scan_mode)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(scan_count)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(text_direction)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_rotate_bkg180)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_check_dogear)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(dogear_size)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_check_skew)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(skew_range)
|
2022-06-28 09:17:10 +00:00
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(black_white_threshold)
|
2022-09-07 07:48:41 +00:00
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_photo_mode)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(double_feed_handle)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(scan_when_paper_on)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(feed_strength)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(power_scheme)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_auto_strength)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(feed_strength_value)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_reverse_bw)
|
2022-09-10 02:09:37 +00:00
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_hole_l)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(search_hole_range_l)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_hole_r)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(search_hole_range_r)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_hole_t)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(search_hole_range_t)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(is_erase_hole_b)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(search_hole_range_b)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
// SANE-ex option ID:
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_multiout_type)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_auto_color_type)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_color_mode)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_sharpen)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_paper)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_paper_lateral)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_auto_paper_size)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_is_paper_auto_crop)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_text_direction)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_duplex)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_fill_background)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_discard_blank_page)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_discard_blank_receipt)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_is_page_fold)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_color_filter)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_color_enhance)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_final_compression)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_final_format)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_serial)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_to_be_scan)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_scan_with_hole)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_device_code)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_power)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_hardware_version)
|
|
|
|
|
SANE_OPTION_ID_IMPLEMENT(ex_ip)
|
|
|
|
|
|
2022-06-18 00:54:01 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, void, twain_set_transfer(twain_xfer xfer))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
xfer_ = xfer;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-29 08:13:05 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, void, twain_set_compression(SANE_CompressionType compression, void* detail))
|
|
|
|
|
{
|
|
|
|
|
img_fmt_.compress.compression = compression;
|
|
|
|
|
img_fmt_.compress.detail = detail;
|
|
|
|
|
}
|
2022-07-01 07:24:58 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, int, twain_get_config(char* buf, size_t* len))
|
|
|
|
|
{
|
|
|
|
|
std::string cont(cfg_->to_text_stream());
|
|
|
|
|
|
|
|
|
|
if (*len < cont.length())
|
|
|
|
|
{
|
|
|
|
|
*len = cont.length() + 4;
|
|
|
|
|
|
|
|
|
|
return SCANNER_ERR_INSUFFICIENT_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
strcpy(buf, cont.c_str());
|
|
|
|
|
|
|
|
|
|
return SCANNER_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, int, twain_set_config(char* buf, size_t len))
|
|
|
|
|
{
|
|
|
|
|
if(cfg_->load_from_mem(buf))
|
|
|
|
|
{
|
2022-10-08 06:13:09 +00:00
|
|
|
|
update_config();
|
2022-07-01 07:24:58 +00:00
|
|
|
|
apply_config();
|
|
|
|
|
|
|
|
|
|
return SCANNER_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCANNER_ERR_DATA_DAMAGED;
|
|
|
|
|
}
|
2022-06-29 08:13:05 +00:00
|
|
|
|
|
2022-06-18 00:54:01 +00:00
|
|
|
|
|
|
|
|
|
// ui ...
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, ui_show_main(HWND parent))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
return false;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bool indicator))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-20 07:17:55 +00:00
|
|
|
|
SANEAPI api = { NULL };
|
|
|
|
|
|
2022-09-28 12:01:14 +00:00
|
|
|
|
if (with_scan)
|
|
|
|
|
{
|
|
|
|
|
events_.clear();
|
|
|
|
|
images_.clear();
|
|
|
|
|
scan_msg_ = "OK";
|
|
|
|
|
scan_err_ = false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-20 07:17:55 +00:00
|
|
|
|
api.sane_cancel_api = inner_sane_cancel;
|
|
|
|
|
api.sane_close_api = inner_sane_close;
|
|
|
|
|
api.sane_control_option_api = inner_sane_control_option;
|
|
|
|
|
api.sane_get_devices_api = inner_sane_get_devices;
|
|
|
|
|
api.sane_get_option_descriptor_api = inner_sane_get_option_descriptor;
|
|
|
|
|
api.sane_get_parameters_api = inner_sane_get_parameters;
|
|
|
|
|
api.sane_get_select_fd_api = inner_sane_get_select_fd;
|
|
|
|
|
api.sane_io_control_api = inner_sane_io_control;
|
|
|
|
|
api.sane_open_api = inner_sane_open;
|
|
|
|
|
api.sane_read_api = inner_sane_read;
|
|
|
|
|
api.sane_set_io_mode_api = inner_sane_set_io_mode;
|
|
|
|
|
api.sane_start_api = inner_sane_start;
|
|
|
|
|
api.sane_strstatus_api = inner_sane_strstatus;
|
|
|
|
|
|
2022-10-08 09:20:16 +00:00
|
|
|
|
size_t pid = scanner_name_.find(L" - ");
|
|
|
|
|
if (pid == -1)
|
|
|
|
|
pid = scanner_name_.length();
|
|
|
|
|
setting_.reset(new dlg_setting(parent, &api, handle_, with_scan, scanner_name_.substr(0, pid).c_str()));
|
2022-06-27 01:38:12 +00:00
|
|
|
|
setting_->set_ui_event_notify(&scanner::ui_callback, this);
|
2022-10-08 09:20:16 +00:00
|
|
|
|
setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid)).c_str());
|
2022-07-01 07:24:58 +00:00
|
|
|
|
cfg_->begin_setting();
|
2022-07-02 09:27:21 +00:00
|
|
|
|
indicator_.reset();
|
|
|
|
|
if (indicator)
|
2022-06-27 01:38:12 +00:00
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
indicator_.reset(new dlg_indicator(setting_->hwnd()));
|
2022-06-27 01:38:12 +00:00
|
|
|
|
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
|
|
|
|
|
}
|
2022-07-01 07:24:58 +00:00
|
|
|
|
setting_->show(true);
|
2022-06-18 08:48:41 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-07-28 01:57:26 +00:00
|
|
|
|
if(setting_.get() && IsWindowVisible(setting_->hwnd()))
|
|
|
|
|
parent = setting_->hwnd();
|
|
|
|
|
|
2022-06-20 07:17:55 +00:00
|
|
|
|
indicator_.reset(new dlg_indicator(parent));
|
2022-06-27 01:38:12 +00:00
|
|
|
|
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
|
2022-07-02 09:27:21 +00:00
|
|
|
|
indicator_->show(true);
|
2022-06-18 08:48:41 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanner, void, ui_hide(void))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-18 08:48:41 +00:00
|
|
|
|
if (indicator_.get())
|
|
|
|
|
indicator_.reset();
|
2022-06-20 07:17:55 +00:00
|
|
|
|
if (setting_.get())
|
|
|
|
|
setting_.reset();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void))
|
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
return true;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-01 07:24:58 +00:00
|
|
|
|
// called from device-layer ...
|
2022-07-02 09:27:21 +00:00
|
|
|
|
int scanner::handle_device_event(int ev_code, void* data, unsigned int* len)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-07-01 07:24:58 +00:00
|
|
|
|
if (ev_code == SANE_EVENT_WORKING)
|
|
|
|
|
{
|
|
|
|
|
if (indicator_.get())
|
|
|
|
|
indicator_->notify_working();
|
2022-07-02 09:27:21 +00:00
|
|
|
|
else
|
|
|
|
|
events_.save(ev_code);
|
2022-09-19 06:16:34 +00:00
|
|
|
|
|
|
|
|
|
log_info(L"Scanning ...\r\n", 0);
|
2022-07-01 07:24:58 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ev_code == SANE_EVENT_IMAGE_OK)
|
2022-06-18 00:54:01 +00:00
|
|
|
|
{
|
|
|
|
|
SANE_Image* simg = (SANE_Image*)data;
|
|
|
|
|
scanned_img* img = NULL;
|
|
|
|
|
wchar_t name[40] = { 0 };
|
|
|
|
|
|
|
|
|
|
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
|
2022-06-29 08:13:05 +00:00
|
|
|
|
img = new scanned_img(handle_, simg->header, simg->data, simg->bytes, dpi_, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
|
|
|
|
|
if (img->bytes() /*>= simg->bytes*/)
|
2022-06-18 00:54:01 +00:00
|
|
|
|
{
|
2022-09-20 10:14:27 +00:00
|
|
|
|
img->set_image_status((SANE_Image_Statu)simg->flag.statu);
|
2022-06-18 00:54:01 +00:00
|
|
|
|
images_.save(img);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
img->release();
|
|
|
|
|
}
|
2022-07-02 09:27:21 +00:00
|
|
|
|
if (indicator_.get())
|
2022-06-18 08:48:41 +00:00
|
|
|
|
indicator_->notify_data_arrived(true);
|
2022-09-19 06:16:34 +00:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
wchar_t msg[128] = { 0 };
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"New image(%u) received with %u bytes\r\n", img_ind_, simg->bytes);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-18 08:48:41 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED)
|
|
|
|
|
{
|
2022-07-02 09:27:21 +00:00
|
|
|
|
if (indicator_.get())
|
2022-06-18 08:48:41 +00:00
|
|
|
|
indicator_->notify_data_arrived(false);
|
2022-06-18 00:54:01 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ev_code == SANE_EVENT_SCAN_FINISHED)
|
|
|
|
|
{
|
2022-06-18 08:48:41 +00:00
|
|
|
|
if (indicator_.get())
|
2022-07-02 09:27:21 +00:00
|
|
|
|
indicator_->notify_scan_over((char*)data, *len != SCANNER_ERR_OK);
|
|
|
|
|
else
|
|
|
|
|
events_.save(ev_code);
|
2022-09-19 06:16:34 +00:00
|
|
|
|
is_scanning_ = false;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
wchar_t msg[128] = { 0 };
|
|
|
|
|
swprintf_s(msg, _countof(msg) - 1, L"Scan finished with error: %u\r\n", *len);
|
|
|
|
|
log_info(msg, 0);
|
|
|
|
|
}
|
2022-06-18 00:54:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-09-22 08:25:03 +00:00
|
|
|
|
int scanner::last_error(void)
|
|
|
|
|
{
|
|
|
|
|
return err_;
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-18 00:54:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-09-19 06:16:34 +00:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// log ...
|
|
|
|
|
#include <direct.h>
|
|
|
|
|
|
|
|
|
|
std::mutex g_lock_;
|
2022-10-08 09:20:16 +00:00
|
|
|
|
std::string g_path_file_("");
|
2022-09-19 06:16:34 +00:00
|
|
|
|
FILE* g_file_ = NULL;
|
|
|
|
|
|
|
|
|
|
void init_log(void)
|
|
|
|
|
{
|
|
|
|
|
char* tmp = getenv("LOCALAPPDATA");
|
|
|
|
|
if (tmp)
|
|
|
|
|
{
|
|
|
|
|
std::string path(tmp);
|
|
|
|
|
char name[MAX_PATH] = { 0 }, * last = NULL;
|
|
|
|
|
|
|
|
|
|
path += std::string("\\") + PRODUCT_VENDOR + "Scan\\Log\\";
|
|
|
|
|
mkdir(path.c_str());
|
|
|
|
|
GetModuleFileNameA(NULL, name, _countof(name) - 1);
|
|
|
|
|
last = strrchr(name, '\\');
|
|
|
|
|
if (last++ == NULL)
|
|
|
|
|
last = name;
|
|
|
|
|
path += last;
|
|
|
|
|
path += "_twain.log";
|
2022-10-08 09:20:16 +00:00
|
|
|
|
g_file_ = fopen(path.c_str(), "a+b");
|
|
|
|
|
g_path_file_ = path;
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char name[MAX_PATH] = { 0 }, * last = NULL;
|
|
|
|
|
std::string path("");
|
|
|
|
|
|
|
|
|
|
GetModuleFileNameA(NULL, name, _countof(name) - 1);
|
|
|
|
|
path = std::string(name) + "_twain.log";
|
2022-10-08 09:20:16 +00:00
|
|
|
|
g_file_ = fopen(path.c_str(), "a+b");
|
|
|
|
|
g_path_file_ = path;
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
2022-09-27 04:35:37 +00:00
|
|
|
|
if (g_file_)
|
|
|
|
|
{
|
2022-10-08 09:20:16 +00:00
|
|
|
|
fseek(g_file_, 0, SEEK_END);
|
|
|
|
|
if (ftell(g_file_))
|
|
|
|
|
{
|
|
|
|
|
std::wstring sep(L"\r\n\r\n\r\n=================================================\r\n");
|
|
|
|
|
fwrite(sep.c_str(), 2, sep.length(), g_file_);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned short bom = 0x0feff;
|
|
|
|
|
fwrite(&bom, sizeof(bom), 1, g_file_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
struct tm* t = localtime(&now);
|
|
|
|
|
wchar_t ts[128] = { 0 };
|
|
|
|
|
|
|
|
|
|
swprintf_s(ts, _countof(ts) - 1, L"==================%04d-%02d-%02d %02d:%02d:%02d==================\r\n"
|
|
|
|
|
, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
|
|
|
|
fwrite(ts, 2, lstrlenW(ts), g_file_);
|
2022-09-27 04:35:37 +00:00
|
|
|
|
}
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
|
|
|
|
void close_log(void)
|
|
|
|
|
{
|
|
|
|
|
if (g_file_)
|
|
|
|
|
fclose(g_file_);
|
|
|
|
|
g_file_ = NULL;
|
|
|
|
|
}
|
|
|
|
|
void log(const wchar_t* info)
|
|
|
|
|
{
|
|
|
|
|
if (g_file_)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_lock_);
|
|
|
|
|
|
|
|
|
|
fwrite(info, 2, lstrlenW(info), g_file_);
|
|
|
|
|
fflush(g_file_);
|
|
|
|
|
if (ftell(g_file_) > 10 * 1024 * 1024)
|
2022-10-08 09:20:16 +00:00
|
|
|
|
{
|
|
|
|
|
fclose(g_file_);
|
|
|
|
|
remove(g_path_file_.c_str());
|
|
|
|
|
g_file_ = fopen(g_path_file_.c_str(), "a+b");
|
|
|
|
|
if (g_file_)
|
|
|
|
|
{
|
|
|
|
|
unsigned short bom = 0x0feff;
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
struct tm* t = localtime(&now);
|
|
|
|
|
wchar_t ts[128] = { 0 };
|
|
|
|
|
|
|
|
|
|
swprintf_s(ts, _countof(ts) - 1, L"==================%04d-%02d-%02d %02d:%02d:%02d (Truncated when size > 10MB) ==================\r\n"
|
|
|
|
|
, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
|
|
|
|
fwrite(&bom, sizeof(bom), 1, g_file_);
|
|
|
|
|
fwrite(ts, 2, lstrlenW(ts), g_file_);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-19 06:16:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// exports
|
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
int __stdcall initialize(void* reserve)
|
|
|
|
|
{
|
2022-09-19 06:16:34 +00:00
|
|
|
|
init_log();
|
2022-06-18 00:54:01 +00:00
|
|
|
|
hg_sane_middleware::set_callback(callback::sane_event_callback, NULL);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
hg_sane_middleware::instance();
|
|
|
|
|
|
|
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
|
}
|
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
int __stdcall open_scanner(SCANNERID scanner_id, ISaneInvoker** invoker)
|
|
|
|
|
{
|
|
|
|
|
if (!invoker)
|
|
|
|
|
return SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (!is_scanner_online(scanner_id))
|
|
|
|
|
return SCANNER_ERR_DEVICE_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
scanner* scn = new scanner(scanner_id);
|
2022-09-22 08:25:03 +00:00
|
|
|
|
if (scn->last_error() == SCANNER_ERR_OK)
|
|
|
|
|
{
|
|
|
|
|
*invoker = dynamic_cast<ISaneInvoker*>(scn);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-09-22 08:25:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int ret = scn->last_error();
|
|
|
|
|
|
|
|
|
|
scn->release();
|
|
|
|
|
*invoker = NULL;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
bool __stdcall is_scanner_online(SCANNERID scanner_id)
|
|
|
|
|
{
|
|
|
|
|
return !scanner::get_scanner_name(scanner_id).empty();
|
|
|
|
|
}
|
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
int __stdcall uninitialize(void* reserve)
|
|
|
|
|
{
|
2022-06-18 00:54:01 +00:00
|
|
|
|
hg_sane_middleware::set_callback(NULL, NULL);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
hg_sane_middleware::clear();
|
2022-09-19 06:16:34 +00:00
|
|
|
|
close_log();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2022-09-19 06:16:34 +00:00
|
|
|
|
#ifdef EXPORT_SANE_API
|
|
|
|
|
__declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
__declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
void __stdcall log_info(const wchar_t* info, int level)
|
|
|
|
|
{
|
|
|
|
|
log(info);
|
|
|
|
|
}
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|