code_twain/sane/scanner.cpp

3774 lines
111 KiB
C++
Raw Normal View History

2023-08-03 03:22:09 +00:00

2023-04-23 14:23:02 +00:00
#include "scanner.h"
2022-06-15 03:04:40 +00:00
#include <Windows.h>
#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>
2023-05-19 07:03:38 +00:00
#include <twain_user/twainui.h>
2023-04-23 14:23:02 +00:00
#include "DlgSetting.h"
2022-07-01 07:24:58 +00:00
#include "gb_json.h"
2023-01-29 07:03:32 +00:00
#include "../../sdk/include/lang/app_language.h"
#include <functional>
2023-04-23 14:23:02 +00:00
#include "DlgIndicator.h"
#include <twain_user/twainui.h>
#pragma comment(lib, "Shlwapi.lib")
#define START_SCAN_IN_THREAD
2022-06-15 03:04:40 +00:00
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
#define SET_SANE_OPT_ID(id, id_name, name, val, extension) \
if(strcmp(SANE_STD_OPT_NAME_##name, val) == 0) \
{ \
id_name##_id_ = id; \
sane_ids_[(sane_option_id)SANE_OPT_ID_##name] = id; \
extension(id); \
2022-06-15 03:04:40 +00:00
}
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
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);
extern const char* inner_sane_err_desc(SANE_Status err);
}
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;
2023-08-03 03:22:09 +00:00
int sane_event_callback( // 娉ㄥ唽鍥炶皟鐨勫璞★紝闇€瑕佷繚璇佽鍥炶皟鏄绾跨▼瀹夊叏鐨?
SANE_Handle hdev // 浜х敓浜嬩欢鐨勮澶囧彞鏌?
, int code // 鍥炶皟浜嬩欢浠g爜
, void* data // 鍥炶皟浜嬩欢鏁版嵁锛屾牴鎹簨浠朵唬鐮佹湁鎵€涓嶅悓锛屽弬鐓у叿浣撲簨浠跺畾涔?
, unsigned int* len // 鏁版嵁闀垮害锛堝瓧鑺傦級锛屾垨鑰卐vent_data鐨勭紦鍐插尯闀垮害锛岃缁嗚鐪嬬浉搴旂殑浜嬩欢浠
, void* param // 鐢ㄦ埛鑷畾涔夋暟鎹紝涓庤皟鐢╯ane_init_ex浼犲叆鏃剁殑淇濇寔涓€鑷?
) // 杩斿洖鍊间緷涓嶅悓鐨勪簨浠朵唬鐮佽€屽畾锛岄€氬父涓衡€?鈥?
2022-06-18 00:54:01 +00:00
{
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())
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);
2023-05-20 04:02:26 +00:00
log_info(msg, 1);
2022-09-21 08:44:41 +00:00
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}
, {SANE_STD_OPT_NAME_FOLD_TYPE , OPTION_TITLE_DZMS}
, {SANE_STD_OPT_NAME_COLOR_CORRECTION , OPTION_TITLE_SPJZ}
2022-10-08 06:13:09 +00:00
},
2023-08-03 03:22:09 +00:00
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"} // 榛戠櫧鍥惧儚鍙嶈壊杈撳嚭锛堟甯搁鑹蹭负锛?-榛戣壊锛?-鐧借壊锛?
, {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"} // " 鎼撶焊闃堝€?
2022-10-08 06:13:09 +00:00
};
2022-10-28 09:09:59 +00:00
const char* option_title_2_name(const char* title)
2022-10-08 06:13:09 +00:00
{
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 "";
}
static BOOL CALLBACK main_wnd(HWND hwnd, LPARAM param)
{
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
if (pid != GetCurrentProcessId())
return TRUE;
if (((void**)param)[1] == NULL)
{
HWND parent = GetParent(hwnd);
while (IsWindow(parent))
{
hwnd = parent;
parent = GetParent(hwnd);
}
parent = hwnd;
if (!IsWindowVisible(parent))
return TRUE;
RECT r = { 0 };
GetWindowRect(parent, &r);
if (RECT_H(r) > 50 && RECT_W(r) > 50)
{
*(HWND*)param = parent;
return FALSE;
}
}
else
{
wchar_t val[128] = { 0 };
GetClassNameW(hwnd, val, _countof(val) - 1);
if (wcscmp(val, L"#32770"))
return TRUE;
GetWindowTextW(hwnd, val, _countof(val) - 1);
if (*((std::wstring**)param)[1] == val)
{
*(HWND*)param = hwnd;
return FALSE;
}
}
return TRUE;
}
static HWND find_main_wnd(void)
{
HWND wnd[2] = { NULL };
EnumWindows(main_wnd, (LPARAM)wnd);
return wnd[0];
}
static DWORD WINAPI btm(LPVOID para)
{
std::wstring* title[2] = { NULL, (std::wstring*)para };
Sleep(100);
EnumWindows(main_wnd, (LPARAM)title);
if (IsWindow((HWND)title[0]))
{
RECT r = { 0 };
GetWindowRect((HWND)title[0], &r);
SetWindowPos((HWND)title[0], HWND_TOPMOST, r.left, r.top, RECT_W(r), RECT_H(r), SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
SetFocus((HWND)title[0]);
}
delete title[1];
return 0;
}
static void bring_message_box_topmost(const wchar_t* title)
{
DWORD id = 0;
std::wstring* t(new std::wstring(title));
HANDLE h = CreateThread(NULL, 0, btm, t, 0, &id);
if (h)
CloseHandle(h);
else
delete t;
}
static const char* __stdcall language_trans(const char* in, bool from_hz, void* param)
{
if (from_hz)
return from_default_language(in, nullptr);
else
return to_default_language(in, nullptr);
}
// UI ...
//
// events code, see SANE_Event
//
// callback events: SANE_EVENT_UI_CLOSE_CANCEL/SANE_EVENT_UI_CLOSE_NORMAL/SANE_EVENT_UI_SCAN_COMMAND/SANE_EVENT_UI_CLOSE_SETTING
//
// notify events: SANE_EVENT_WORKING - void*: unused, be NULL, flag - unused, be 0
// SANE_EVENT_SCAN_FINISHED - void*: (utf8*)message, flag - error code (0 is success)
// SANE_EVENT_USB_DATA_RECEIVED- void* unused, be NULL, flag - unused, be 0
// SANE_EVENT_IMAGE_OK - void* unused, be NULL, flag - unused, be 0
2023-05-20 04:02:26 +00:00
static HMODULE hui = NULL;
2023-04-23 14:23:02 +00:00
int (*choose_scanner)(const std::vector<DEVQUEUI>& devs) = NULL; // blocked. return selected DEVQUE::id or -1 if user cancelled
2023-08-03 03:22:09 +00:00
char* (*apply_current_config)(const char* dev_name, SANE_Handle device, LPSANEAPI api) = NULL; // 搴旂敤璁惧鐨勫綋鍓嶉厤锟?
2023-05-05 09:53:46 +00:00
int (*show_setting_ui)(SANE_Handle device, HWND parent, LPSANEAPI api, const char* devname, bool with_scan, std::function<void(ui_result)> callback) = NULL;
int (*show_progress_ui)(HWND parent, std::function<void(ui_result)> callback, std::function<void(int/*event*/, void*/*msg*/, int/*flag*/)>* notify) = NULL;
int (*show_messagebox_ui)(HWND parent, int event, void* msg, int flag) = NULL;
2023-05-19 07:03:38 +00:00
int (*close_ui)(int) = NULL;
2023-08-03 03:22:09 +00:00
int (*apply_given_config)(const char* content, SANE_Handle device, LPSANEAPI api) = NULL; // 搴旂敤鎸囧畾鐨勯厤缃紝content涓洪厤缃暟鎹祦
char* (*get_config_content)(const char* dev_name, const char* name) = NULL;
void (*twain_ui_free)(void* buf) = NULL;
2023-04-23 14:23:02 +00:00
static void init_ui(void)
{
std::string root(hg_sane_middleware::sane_path());
2023-06-02 02:54:48 +00:00
root += OEM_SHORT_NAME_E;
root += "TwainUI.dll";
2023-05-20 04:02:26 +00:00
hui = LoadLibraryExA(root.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hui)
{
std::wstring info(L"Load '" + local_trans::a2u(root.c_str(), CP_UTF8));
info += L"' failed: " + std::to_wstring(GetLastError()) + L"\r\n";
2023-05-20 04:02:26 +00:00
log_info(info.c_str(), 1);
}
else
{
#define GET_API(api) \
proc = (FARPROC*)&api; \
2023-05-20 04:02:26 +00:00
*proc = GetProcAddress(hui, #api);
FARPROC* proc = NULL;
GET_API(choose_scanner);
GET_API(apply_current_config);
GET_API(show_setting_ui);
GET_API(show_progress_ui);
GET_API(show_messagebox_ui);
2023-05-19 07:03:38 +00:00
GET_API(close_ui);
GET_API(twain_ui_free);
GET_API(apply_given_config);
GET_API(get_config_content);
}
}
2023-05-20 04:02:26 +00:00
static void unint_ui(void)
{
2023-05-23 08:10:40 +00:00
if (close_ui)
2023-05-24 00:44:59 +00:00
close_ui(UI_UNLOAD_MODULE);
2023-05-20 04:02:26 +00:00
choose_scanner = NULL;
apply_current_config = NULL;
show_setting_ui = NULL;
show_progress_ui = NULL;
show_messagebox_ui = NULL;
close_ui = NULL;
twain_ui_free = NULL;
apply_given_config = NULL;
get_config_content = NULL;
2023-05-20 04:02:26 +00:00
if (hui)
{
FreeLibrary(hui);
hui = NULL;
}
}
// check thread whether has window
static BOOL WINAPI check_window(HWND hwnd, LPARAM lp)
{
LPDWORD id = (LPDWORD)lp;
if (GetWindowThreadProcessId(hwnd, NULL) == id[0])
{
id[1] = 1;
return FALSE;
}
return TRUE;
}
static bool is_thread_has_window(DWORD thread_id = -1)
{
if (thread_id == -1)
thread_id = GetCurrentThreadId();
DWORD param[] = { thread_id, 0 };
EnumWindows(check_window, (LPARAM)param);
return param[1];
}
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)
, 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)
, scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL), user_cancel_(false)
, max_img_mem_(1 * 1024), twain_set_(false), ev_cnt_(0), is_bIndicator(false), is_show_setting_(false)
2022-06-15 03:04:40 +00:00
{
ui_notify = std::function<void(int, void*, int)>();
sane_api_.sane_cancel_api = inner_sane_cancel;
sane_api_.sane_close_api = inner_sane_close;
sane_api_.sane_control_option_api = inner_sane_control_option;
sane_api_.sane_get_devices_api = inner_sane_get_devices;
sane_api_.sane_get_option_descriptor_api = inner_sane_get_option_descriptor;
sane_api_.sane_get_parameters_api = inner_sane_get_parameters;
sane_api_.sane_get_select_fd_api = inner_sane_get_select_fd;
sane_api_.sane_io_control_api = inner_sane_io_control;
sane_api_.sane_open_api = inner_sane_open;
sane_api_.sane_read_api = inner_sane_read;
sane_api_.sane_set_io_mode_api = inner_sane_set_io_mode;
sane_api_.sane_start_api = inner_sane_start;
sane_api_.sane_strstatus_api = inner_sane_strstatus;
if (!callback::show_setting_ui)
{
cfg_ = new gb::scanner_cfg();
cfg_->set_language_transform(&callback::language_trans, NULL);
}
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
{
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"\\";
tmp_path_ += L"imgs";
CreateDirectoryW(tmp_path_.c_str(), NULL);
tmp_path_ += L"\\";
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
2022-06-29 08:13:05 +00:00
img_fmt_.compress.compression = SANE_COMPRESSION_NONE;
int mem_limit = GetPrivateProfileIntW(L"mem", L"max_img", 0, (cfg_path_ + L"debug.cfg").c_str());
if (mem_limit > 0)
{
// this value is same as driver memory limit ...
max_img_mem_ = mem_limit;
}
2022-06-15 03:04:40 +00:00
err_ = open();
}
scanner::~scanner()
2022-06-18 00:54:01 +00:00
{
close();
if (thread_starting_.get() && thread_starting_->joinable())
thread_starting_->join();
thread_starting_.reset();
2022-07-01 07:24:58 +00:00
if (cfg_)
{
cfg_->release();
cfg_ = NULL;
}
2022-06-18 00:54:01 +00:00
}
2022-06-15 03:04:40 +00:00
bool scanner::is_belong_serial(int vid, int pid, SCANNERID serial)
{
if (vid == PRODUCT_VENDOR_HG)
{
if (GET_SCANNER_VID(serial) == PRODUCT_VENDOR_HG)
{
if (GET_SCANNER_PID(serial) == 0x100)
{
2022-11-17 02:26:53 +00:00
return pid == 0x100 || pid == 0x139;
}
else if (GET_SCANNER_PID(serial) == 0x200)
{
return pid == 0x200 || pid == 0x239;
}
else if (GET_SCANNER_PID(serial) == 0x300)
{
return pid == 0x300 || pid == 0x302 || pid == 0x339;
}
else if (GET_SCANNER_PID(serial) == 0x400)
{
return pid == 0x400 || pid == 0x402 || pid == 0x439;
}
2022-11-17 02:26:53 +00:00
else if (GET_SCANNER_PID(serial) == 0x138 ||
GET_SCANNER_PID(serial) == 0x238 ||
GET_SCANNER_PID(serial) == 0x303 ||
GET_SCANNER_PID(serial) == 0x404) // OEM_CANGTIAN
return true;
}
2023-01-13 09:46:27 +00:00
return false;
}
else if (vid == PRODUCT_VENDOR_HG1)
{
return pid == 0x7823 && GET_SCANNER_VID(serial) == PRODUCT_VENDOR_HG && GET_SCANNER_PID(serial) == 0x200;
}
else if (vid == PRODUCT_VENDOR_HW)
{
return GET_SCANNER_VID(serial) == vid && GET_SCANNER_PID(serial) == pid;
}
else if (vid == PRODUCT_VENDOR_LSC)
{
if (GET_SCANNER_VID(serial) == PRODUCT_VENDOR_LSC)
{
if (GET_SCANNER_PID(serial) == 0x8420)
{
return pid == 0x8200 || pid == 0x8420 || pid == 0x8429;
}
else if (GET_SCANNER_PID(serial) == 0x8520)
{
return pid == 0x8520 || pid == 0x8529;
}
else if (GET_SCANNER_PID(serial) == 0x8620)
{
return pid == 0x8620 || pid == 0x8629;
}
else if (GET_SCANNER_PID(serial) == 0x8730)
{
return pid == 0x8730 || pid == 0x8739;
}
}
2023-01-13 09:46:27 +00:00
return false;
}
2023-07-20 01:21:31 +00:00
else if (vid == PRODUCT_VENDOR_DL)
{
if (GET_SCANNER_VID(serial) == PRODUCT_VENDOR_DL)
{
if (GET_SCANNER_PID(serial) == 0x401C)
{
2023-08-01 02:40:37 +00:00
return pid == 0x401C || pid == 0x401D || pid == 0x401E || pid == 0x401F || pid == 0x4020 || pid == 0x4021 || pid == 0x4022;
2023-07-20 01:21:31 +00:00
}
else if (GET_SCANNER_PID(serial) == 0x4015)
{
return pid == 0x4015 || pid == 0x4016 || pid == 0x4017 || pid == 0x4018;
}
else if (GET_SCANNER_PID(serial) == 0x4019)
{
return pid == 0x4019 || pid == 0x401A || pid == 0x401B;
}
}
return false;
}
2023-01-13 09:46:27 +00:00
return true;
}
void scanner::get_scanner_name(SCANNERID id, std::vector<std::string>& names)
2022-06-15 03:04:40 +00:00
{
ScannerInfo* devs = NULL;
long count = 0;
names.clear();
2022-06-15 03:04:40 +00:00
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
count++;
devs = new ScannerInfo[count];
memset(devs, 0, count * sizeof(*devs));
2022-06-15 03:04:40 +00:00
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_OK)
{
for (int i = 0; i < count; ++i)
{
if (scanner::is_belong_serial(devs[i].vid, devs[i].pid, id))
2022-06-15 03:04:40 +00:00
{
names.push_back(devs[i].name);
2022-06-15 03:04:40 +00:00
}
}
}
delete[] devs;
}
}
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 scanner::control_read_string(SANE_Handle hdev, int code, std::string& str)
{
char* buf = NULL;
unsigned len = 0;
int err = hg_sane_middleware::instance()->io_control(hdev, code, buf, &len);
str = "";
if (err == SANE_STATUS_NO_MEM)
{
len += 4;
buf = new char[len];
memset(buf, 0, len);
err = hg_sane_middleware::instance()->io_control(hdev, code, buf, &len);
if (err == SANE_STATUS_GOOD)
str = buf;
delete[] buf;
}
return err;
}
2022-06-15 03:04:40 +00:00
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
}
void __stdcall scanner::ui_callback(int uev, void* sender, void* param)
2022-06-18 08:48:41 +00:00
{
((scanner*)param)->on_ui_event(uev, sender);
2022-06-18 08:48:41 +00:00
}
2022-10-28 09:09:59 +00:00
bool scanner::is_option_float(int sn, void* param)
2022-10-08 06:13:09 +00:00
{
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor((SANE_Handle)param, (const void*)sn);
2022-10-08 06:13:09 +00:00
if (desc)
return desc->type == SANE_TYPE_FIXED;
else
return false;
}
void __stdcall scanner::apply_scheme(gb::sane_config_schm* schm, void* param)
{
((scanner*)param)->apply_scheme(schm);
}
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();
}
int scanner::transfer_id(int id)
{
if (id > SANE_OPT_ID_BASE)
{
if (sane_ids_.count((sane_option_id)id) == 0)
id = -1;
else
id = sane_ids_[(sane_option_id)id];
}
return id;
}
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::lang_trans_between_hz936(L"\u534E\u9AD8\u626B\u63CF\u4EEA\u2014");
}
else if (scanner_name_.find(L"LANXUMSCAN ") != std::wstring::npos)
{
old = local_trans::lang_trans_between_hz936(L"\u7ACB\u601D\u8FB0\u626B\u63CF\u4EEA\u2014");
pid += L"S";
}
old += pid;
if (PathFileExistsW((cfg_path_ + old).c_str()))
{
2023-05-20 04:02:26 +00:00
log_info((L"Rename config file '" + old + L"' to '" + scanner_name_.substr(0, pos) + L"'\r\n").c_str(), 1);
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)
{
if (!cfg_)
return;
gb::sane_config_schm* schm = cfg_->get_scheme();
2022-10-08 06:13:09 +00:00
std::string notice("");
if (schm)
{
//schm->update(&scanner::is_option_float, handle_, &callback::option_title_2_name, &notice);
//if (notice.length())
//{
// std::wstring msg(local_trans::lang_trans_between_hz936(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") + L"\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");
// }
// if (!IsWindow(app_wnd_))
// callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str());
// MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str(), MB_OK | MB_ICONINFORMATION);
//}
schm->release();
2022-10-08 06:13:09 +00:00
}
}
2022-07-01 07:24:58 +00:00
void scanner::load_config(const wchar_t* file)
{
if (cfg_)
{
cfg_->load_file(local_trans::u2a(file).c_str());
update_config();
}
2022-07-01 07:24:58 +00:00
}
void scanner::save_config(const wchar_t* file)
{
if(cfg_)
cfg_->save(local_trans::u2a(file).c_str());
2022-07-01 07:24:58 +00:00
}
void scanner::apply_config(void)
{
if (callback::apply_current_config)
{
char* cfg = callback::apply_current_config(local_trans::u2a(scanner_name_.c_str(), CP_UTF8).c_str(), handle_, &sane_api_);
if (cfg && callback::twain_ui_free)
callback::twain_ui_free(cfg);
}
else if (cfg_)
{
gb::sane_config_schm* schm = cfg_->get_scheme();
2022-10-08 06:13:09 +00:00
if (!schm)
return;
2022-10-08 06:13:09 +00:00
apply_scheme(schm);
schm->release();
}
2022-07-01 07:24:58 +00:00
}
void scanner::on_ui_event(int uev, void* sender)
2022-06-18 08:48:41 +00:00
{
if (uev == SANE_EVENT_UI_CLOSE_SETTING)
{
// setting UI closed ...
is_scanning_ = is_show_setting_ = false;
if (setting_.get())
setting_.reset();
}
else if (uev == SANE_EVENT_UI_CLOSE_NORMAL)
{
// scan complete
if (indicator_.get())
indicator_.reset();
// FIX on 2023-05-30: restore scan finished status, whether close UI is up to APP
//is_scanning_ = is_show_setting_;
is_scanning_ = false;
ui_notify = std::function<void(int, void*, int)>();
}
else if (uev == SANE_EVENT_UI_CLOSE_CANCEL)
{
// scan cancelled
if (indicator_.get())
indicator_.reset();
stop(); // nothing to do, the finishing work do in SANE_EVENT_SCAN_FINISHED
}
else if (uev == SANE_EVENT_SCAN_FINISHED)
{
// FIX on 2023-05-30: restore scan finished status, whether close UI is up to APP
//is_scanning_ = is_show_setting_;
is_scanning_ = false;
ui_notify = std::function<void(int, void*, int)>();
}
int(__stdcall * h)(int, void*) = scanner_ev_handler_;
if (h)
{
h(uev, evh_param_);
}
return;
events_.save(uev, sizeof(uev));
2022-06-18 08:48:41 +00:00
}
std::string scanner::choose_scanner(const std::vector<std::string>& scanners)
{
if (scanners.empty())
return "";
2023-04-23 14:23:02 +00:00
std::vector<DEVQUEUI> devs;
std::string sel("");
int id = 1;
for (size_t i = 0; i < scanners.size(); ++i)
{
SANE_Handle h = NULL;
int ret = hg_sane_middleware::instance()->open_device(scanners[i].c_str(), &h);
if (h)
{
std::string sn("");
scanner::control_read_string(h, IO_CTRL_CODE_GET_SERIAL, sn);
if (sn.length())
{
2023-04-23 14:23:02 +00:00
DEVQUEUI dev;
dev.id = id++;
dev.name = scanners[i];
dev.sn = sn;
devs.push_back(dev);
}
hg_sane_middleware::instance()->close_device(h);
}
}
if (devs.size() == 0)
sel = scanners[0];
else if (devs.size() == 1)
sel = devs[0].name;
else if (callback::choose_scanner)
{
id = callback::choose_scanner(devs);
if (id != -1)
{
for (auto& v : devs)
{
if (v.id == id)
{
sel = v.name;
break;
}
}
}
}
else
{
2023-04-23 14:23:02 +00:00
//dlg_choose_dev dlg(NULL, devs);
//dlg.show(true, true);
//sel = dlg.get_selected_device();
}
return sel;
}
2022-06-15 03:04:40 +00:00
int scanner::open(void)
{
int ret = close();
std::vector<std::string> que;
std::string name("");
scanner::get_scanner_name(id_, que);
2022-06-15 03:04:40 +00:00
scanner_name_ = L"";
if (que.empty())
2022-06-15 03:04:40 +00:00
return SCANNER_ERR_DEVICE_NOT_FOUND;
if (que.size() == 1)
name = que[0];
else
{
name = choose_scanner(que);
if (name.empty())
return SCANNER_ERR_USER_CANCELED;
}
2022-06-15 03:04:40 +00:00
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
if (ret == SANE_STATUS_GOOD)
{
2022-10-08 09:31:13 +00:00
size_t pid = -1;
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-10-08 09:31:13 +00:00
pid = scanner_name_.find(L" - ");
if (pid == -1)
pid = scanner_name_.length();
2022-06-15 03:04:40 +00:00
ret = init_options_id();
load_config((cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str());
apply_config();
2023-06-13 04:28:56 +00:00
// check roller life ...
SANE_Int cnt = 0, life = 0;
if (hg_sane_middleware::instance()->get_cur_value(handle_, (void*)SANE_OPT_ID_ROLLER_COUNT, &cnt) &&
hg_sane_middleware::instance()->set_option(handle_, (void*)SANE_OPT_ID_ROLLER_LIFE, SANE_ACTION_GET_VALUE, &life, NULL) == SANE_STATUS_GOOD)
//hg_sane_middleware::instance()->get_cur_value(handle_, (void*)SANE_OPT_ID_ROLLER_LIFE, &life))
2023-06-13 04:28:56 +00:00
{
if (cnt >= life / 100 * 99) // 99%
2023-06-13 04:28:56 +00:00
{
if (callback::show_messagebox_ui)
{
2023-08-03 03:22:09 +00:00
// 绾歌疆鎼撶焊娆℃暟宸茶秴杩囪璁′娇鐢ㄨ寖鍥达紝鎵弿杩囩▼涓悡绾稿け璐ャ€佹鏂溿€佹悡澶氬紶绛夊紓甯搁娆″彲鑳戒細鏄庢樉澧炲锛岃娉ㄦ剰鍙婃椂娓呮磥銆佸苟鑱旂郴璁惧渚涘簲鍟嗚喘涔版浛鎹㈢焊杞紒
2023-06-14 01:33:05 +00:00
std::wstring roller_msgw(local_trans::lang_trans_between_hz936(L"\u7EB8\u8F6E\u6413\u7EB8\u6B21\u6570\u5DF2\u8D85\u8FC7\u8BBE\u8BA1\u4F7F\u7528\u8303\u56F4\uFF0C\u626B\u63CF\u8FC7\u7A0B\u4E2D\u6413\u7EB8\u5931\u8D25\u3001\u6B6A\u659C\u3001\u6413\u591A\u5F20\u7B49\u5F02\u5E38\u9891\u6B21\u53EF\u80FD\u4F1A\u660E\u663E\u589E\u591A\uFF0C\u8BF7\u6CE8\u610F\u53CA\u65F6\u6E05\u6D01\u3001\u5E76\u8054\u7CFB\u8BBE\u5907\u4F9B\u5E94\u5546\u8D2D\u4E70\u66FF\u6362\u7EB8\u8F6E\uFF01"));
std::string roller_msg(local_trans::u2a(roller_msgw.c_str(), CP_UTF8));
2023-06-13 04:28:56 +00:00
app_wnd_ = callback::find_main_wnd();
callback::show_messagebox_ui(app_wnd_, ret, (void*)&roller_msg[0], 0);
}
}
}
2022-06-15 03:04:40 +00:00
}
else
{
if (callback::show_messagebox_ui)
{
2023-06-13 04:28:56 +00:00
app_wnd_ = callback::find_main_wnd();
callback::show_messagebox_ui(app_wnd_, ret, (void*)hg_scanner_err_description(ret), 0);
}
else
{
std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8));
//if (indicator_.get())
// indicator_->show(false);
if (!IsWindow(app_wnd_))
callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str());
MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str(), MB_OK | MB_ICONERROR);
}
}
2022-06-15 03:04:40 +00:00
return ret;
}
int scanner::close(void)
{
scanner_ev_handler_ = NULL;
ui_hide();
2022-09-21 08:44:41 +00:00
callback::unreg_callback(this);
2022-06-15 03:04:40 +00:00
if (handle_)
{
2022-06-15 03:04:40 +00:00
hg_sane_middleware::instance()->close_device(handle_);
}
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
#define INIT_FIXED_IDS(id) \
2023-06-13 04:28:56 +00:00
sane_ids_[SANE_OPT_ID_##id] = SANE_OPT_ID_##id;
INIT_FIXED_IDS(HISTORY_COUNT);
INIT_FIXED_IDS(DRIVER_VERSION);
INIT_FIXED_IDS(MANUFACTURER);
INIT_FIXED_IDS(COPYRIGHT);
INIT_FIXED_IDS(CO_URL);
INIT_FIXED_IDS(CO_TEL);
INIT_FIXED_IDS(CO_ADDR);
INIT_FIXED_IDS(CO_GPS);
INIT_FIXED_IDS(HELP);
INIT_FIXED_IDS(VID);
INIT_FIXED_IDS(PID);
INIT_FIXED_IDS(DEV_NAME);
INIT_FIXED_IDS(DEV_FAMILY);
INIT_FIXED_IDS(LOGIN);
INIT_FIXED_IDS(LOGOUT);
INIT_FIXED_IDS(ROLLER_COUNT);
INIT_FIXED_IDS(DRIVER_LOG);
INIT_FIXED_IDS(DEVICE_LOG);
INIT_FIXED_IDS(ROLLER_LIFE);
INIT_FIXED_IDS(DEVICE_MAC_ADDR);
INIT_FIXED_IDS(CUSTOM_GAMMA);
2023-06-17 05:29:39 +00:00
INIT_FIXED_IDS(MOTOR_VER);
while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (const void*)op_id)))
2022-06-15 03:04:40 +00:00
{
void* val = hg_sane_middleware::instance()->get_def_value(handle_, (void*)op_id, NULL, true);
2022-07-01 07:24:58 +00:00
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 && cfg_)
2023-01-29 07:03:32 +00:00
{
if (desc->type == SANE_TYPE_STRING)
{
std::string deflan(to_default_language((char*)val, nullptr));
cfg_->set_default_value(op_id, desc->name, desc->title, &deflan[0], deflan.length(), desc->type);
2023-01-29 07:03:32 +00:00
}
else
cfg_->set_default_value(op_id, desc->name, desc->title, (char*)val, len, desc->type);
2023-01-29 07:03:32 +00:00
}
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-10-24 08:58:09 +00:00
else SET_OPT_ID(fold_direction, FOLD_TYPE, extension_none)
else SET_OPT_ID(color_correction, COLOR_CORRECTION, extension_none)
else SET_OPT_ID(language, LANGUAGE, 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; \
ea.base_ind = -1; \
2022-06-15 03:04:40 +00:00
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);
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)
{
2023-08-03 03:22:09 +00:00
// 鍏煎鑰佺殑闄ゅ瓟绠楁硶
2022-09-12 06:45:07 +00:00
EXAPI ea;
ea.ind = is_erase_hole_id_ = ex_id_++;
2022-10-14 02:11:43 +00:00
ea.base_ind = is_erase_hole_l_id_;
2022-09-12 06:45:07 +00:00
ea.ex_api = &scanner::handle_ex_erase_hole;
ex_opts_.push_back(ea);
ea.ind = search_hole_range_id_ = ex_id_++;
2022-10-14 02:11:43 +00:00
ea.base_ind = search_hole_range_l_id_;
2022-09-12 06:45:07 +00:00
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)
{
return scanner::control_read_string(handle_, code, ret);
2022-06-15 03:04:40 +00:00
}
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_, (const void*)scan_mode_id_);
2022-06-15 03:04:40 +00:00
char* buf = new char[parent->size + 4];
memset(buf, 0, parent->size);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)scan_mode_id_, buf);
handled = compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), buf);
2022-06-15 03:04:40 +00:00
delete[] buf;
if (handled)
{
int count = -1;
value_role role = VAL_ROLE_CURRENT;
buf = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)scan_mode_id_);
if (compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), buf))
2022-06-15 03:04:40 +00:00
role = value_role(role | VAL_ROLE_DEFAULT);
local_utility::free_memory(buf);
setv(&count, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), VAL_LIMIT_NONE, param);
2022-06-15 03:04:40 +00:00
}
}
else
handled = false;
return handled;
}
2023-01-10 09:30:00 +00:00
bool scanner::set_option_value_with_parent(int sn, void* data, int* err) // return true if handled sn
2022-06-15 03:04:40 +00:00
{
2023-01-10 09:30:00 +00:00
bool handled = false;
2022-06-15 03:04:40 +00:00
if (sn == scan_count_id_)
{
SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, (void*)scan_mode_id_);
2022-06-15 03:04:40 +00:00
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_, (void*)scan_mode_id_, val);
if (compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), val))
2022-06-15 03:04:40 +00:00
{
if (*(int*)data != -1)
{
strcpy(val, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_SMZDZS, true, nullptr));
*err = hg_sane_middleware::instance()->set_option(handle_, (void*)scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
2022-06-15 03:04:40 +00:00
}
}
else if (*(int*)data == -1)
{
strcpy(val, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr));
*err = hg_sane_middleware::instance()->set_option(handle_, (void*)scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
2022-06-15 03:04:40 +00:00
}
2022-11-19 00:48:39 +00:00
delete[] val;
2022-06-15 03:04:40 +00:00
}
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;
void* val = data;
2022-06-15 03:04:40 +00:00
if (type == SANE_TYPE_BOOL)
{
sb = *(bool*)data ? SANE_TRUE : SANE_FALSE;
val = &sb;
2022-06-15 03:04:40 +00:00
}
else if (type == SANE_TYPE_INT)
{
si = *(int*)data;
val = &si;
2022-06-15 03:04:40 +00:00
}
else if (type == SANE_TYPE_FIXED)
{
sf = SANE_FIX(*(float*)data);
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());
val = buf;
2022-06-15 03:04:40 +00:00
}
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)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);
}
else if(buf)
{
strcpy((char*)val, buf);
2022-06-15 03:04:40 +00:00
delete[] buf;
}
2022-06-15 03:04:40 +00:00
return ret;
}
int scanner::set_is_multiout(bool enable)
{
int ret = SCANNER_ERR_OK;
if (is_multiout_id_ > 0)
{
SANE_Bool multi = SANE_FALSE;
SANE_Int after = 0;
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)is_multiout_id_, &multi); // parent item ...
if (enable ^ (multi == SANE_TRUE))
{
multi = enable ? SANE_TRUE : SANE_FALSE;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)is_multiout_id_, SANE_ACTION_SET_VALUE, &multi, &after);
after = 0;
}
}
return ret;
}
2022-06-15 03:04:40 +00:00
int scanner::thread_start(void)
{
int ret = hg_sane_middleware::instance()->start(handle_, NULL);
// 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);
if (ret == SANE_STATUS_GOOD)
{
/*if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
indicator_->show(true);*/
unsigned int l = sizeof(img_fmt_);
SANE_CompressionType cmprsn = img_fmt_.compress.compression;
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;
img_fmt_.compress.compression = cmprsn;
}
//else if (indicator_.get())
//{
// indicator_->notify_scan_over(hg_scanner_err_description(ret), true);
//}
else
{
// display error message on progress UI, may be closed immediately by APP, so we hide progress UI and call message_box ...
//
#ifdef START_SCAN_IN_THREAD
if (callback::show_progress_ui && is_bIndicator && ui_notify)
{
int ev = SANE_EVENT_WORKING;
ui_notify(SANE_EVENT_SCAN_FINISHED, (void *)hg_scanner_err_description(ret), ret);
}
else
#endif
{
if (callback::close_ui)
callback::close_ui(UI_INDICATOR);
if (callback::show_messagebox_ui)
{
callback::show_messagebox_ui(app_wnd_, ret, (void*)hg_scanner_err_description(ret), 0);
}
else
{
std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8));
//if (indicator_.get())
// indicator_->show(false);
if (!IsWindow(app_wnd_))
callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str());
MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str(), MB_OK | MB_ICONERROR);
}
is_scanning_ = false;
}
}
prev_start_result_ = ret;
return ret;
}
2022-06-15 03:04:40 +00:00
scanner::EXAPIPOS scanner::find_ex_api(int op_id)
{
return std::find(ex_opts_.begin(), ex_opts_.end(), op_id);
}
void scanner::apply_scheme(gb::sane_config_schm* schm)
{
// restore ...
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_RESTORE_SETTINGS, nullptr, nullptr);
if (!schm)
return;
std::string n(""), v(""), ver(schm->get_version());
if (schm->first_config(n, v))
{
do
{
int id = schm->id_from_name(n.c_str());
if (id == -1)
{
if (gb::sane_config_schm::is_option_data(n))
{
id = schm->id_from_name(n.c_str());
if (id == is_custom_gamma_id_)
{
if (v.length() == sizeof(SANE_Gamma))
{
unsigned int l = v.length();
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &v[0], &l);
}
else
{
wchar_t info[128] = { 0 };
swprintf_s(info, _countof(info) - 1, L"ERROR: custom gamma data length is %u, but we expect %u.\r\n", v.length(), sizeof(SANE_Gamma));
2023-05-20 04:02:26 +00:00
log_info(info, 1);
}
}
}
}
else
{
v = from_default_language(v.c_str(), nullptr);
void* data = &v[0];
SANE_Fixed fixed = 0;
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (const void*)id);
if (desc)
{
char* buf = NULL;
SANE_Int after = 0;
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;
}
hg_sane_middleware::instance()->set_option(handle_, (const void*)id, SANE_ACTION_SET_VALUE, data, &after);
if (buf)
delete[] buf;
}
}
} while (schm->next_config(n, v));
}
}
2022-06-15 03:04:40 +00:00
EX_OPTION_HANDLER_IMPL(multiout)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (void*)base_id);
SANE_Bool parent = SANE_FALSE;
2022-06-15 03:04:40 +00:00
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)is_multiout_id_, &parent);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* cur = (char*)hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id),
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
int now = sane_opt_trans::multiout_value_to_twain(cur),
2022-06-15 03:04:40 +00:00
init = sane_opt_trans::multiout_value_to_twain(def),
val = 0;
local_utility::free_memory(def);
local_utility::free_memory(cur);
2022-06-15 03:04:40 +00:00
{
// parent item ...
if (!parent)
now = MULTI_OUT_NONE;
2022-06-15 03:04:40 +00:00
}
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 (val == init)
role = (value_role)(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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"))
//{
// ret = set_is_multiout(true);
// if (ret == SANE_STATUS_GOOD)
// {
strcpy(val, in);
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, val, &after);
// }
//}
//else
//{
// // disable multi-out, let multiout type aside
// ret = set_is_multiout(false);
//}
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
int init = sane_opt_trans::auto_color_type_to_twain(def);
local_utility::free_memory(def);
2022-06-15 03:04:40 +00:00
len = sane_opt_trans::auto_color_type_to_twain(buf);
set_cur_and_def_value<int>(len, init, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
SANE_Int after = 0;
// ret = set_is_multiout(false);
if (ret == SCANNER_ERR_OK)
{
strcpy(buf, sane_opt_trans::auto_color_type_from_twain(*(int*)data));
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
}
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* cur = (char*)hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id),
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
int now = sane_opt_trans::color_mode_to_twain(cur), // sane_opt_trans::multiout_value_to_twain(cur)
2022-06-15 03:04:40 +00:00
init = sane_opt_trans::color_mode_to_twain(def),
val = 0;
local_utility::free_memory(def);
local_utility::free_memory(cur);
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::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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
break;
}
}
else
set_cur_and_def_value<int>(now, init, setv, data);
} while (0);
}
else
{
SANE_Int after = 0;
// ret = set_is_multiout(false);
if (ret == SCANNER_ERR_OK)
{
char* val = new char[desc->size];
const char* in = sane_opt_trans::color_mode_from_twain(*(int*)data);
strcpy(val, in);
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, val, &after);
delete[] val;
}
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* cur = (char*)hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id),
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
int now = sane_opt_trans::multiout_value_to_twain(cur),
2022-06-15 03:04:40 +00:00
init = sane_opt_trans::sharpen_to_twain(def),
val = 0;
local_utility::free_memory(def);
local_utility::free_memory(cur);
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::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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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;
strcpy(val, in);
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, val, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
2022-06-15 03:04:40 +00:00
int now = sane_opt_trans::paper_to_twain(buf),
init = sane_opt_trans::paper_to_twain(def),
val = 0;
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
}
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
lateral_swap = sane_opt_trans::switch_paper_lateral(buf);
lateral = sane_opt_trans::is_paper_lateral(buf);
if (setv)
{
set_cur_and_def_value<bool>(lateral, false, setv, data);
2022-06-15 03:04:40 +00:00
}
else if (lateral_swap)
{
SANE_Int after = 0;
if (lateral != *(bool*)data)
{
strcpy(buf, lateral_swap);
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_A4HX, true, nullptr));
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-10-07 09:51:09 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
bool yes = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr)) == 0,
def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr)) == 0;
local_utility::free_memory(init);
set_cur_and_def_value<bool>(yes, def, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
SANE_Int after = 0;
strcpy(buf, *(bool*)data ? local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_A4, true, nullptr));
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
if (setv)
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
bool yes = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCCZDCQ, true, nullptr)) == 0,
def = strcmp(init, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0;
local_utility::free_memory(init);
set_cur_and_def_value<bool>(yes, def, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
SANE_Int after = 0;
strcpy(buf, *(bool*)data ? local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCCZDCQ, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCC, true, nullptr));
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
set_cur_and_def_value<bool>(strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0, strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0, setv, data);
local_utility::free_memory(init);
2022-06-15 03:04:40 +00:00
}
else
{
strcpy(buf, val ? local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DM, true, nullptr));
2022-06-15 03:04:40 +00:00
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0;
set_cur_and_def_value<bool>(strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr)) == 0, strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr)) == 0, setv, data);
2022-06-15 03:04:40 +00:00
local_utility::free_memory(init);
}
else
{
strcpy(buf, val ? local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_ADBX, true, nullptr));
2022-06-15 03:04:40 +00:00
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr)) == 0;
local_utility::free_memory(init);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr)) == 0;
set_cur_and_def_value<bool>(val, def, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
if (val)
strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr));
2022-06-15 03:04:40 +00:00
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
2022-06-15 03:04:40 +00:00
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr)) == 0;
local_utility::free_memory(init);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr)) == 0;
set_cur_and_def_value<bool>(val, def, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
if (val)
strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr));
2022-06-15 03:04:40 +00:00
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
2022-06-15 03:04:40 +00:00
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr)) == 0;
local_utility::free_memory(init);
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf);
val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr)) == 0;
set_cur_and_def_value<bool>(val, def, setv, data);
2022-06-15 03:04:40 +00:00
}
else
{
if (val)
strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr));
2022-06-15 03:04:40 +00:00
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id);
2022-06-15 03:04:40 +00:00
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id);
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, buf);
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after);
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_NONE, data);
2022-06-15 03:04:40 +00:00
}
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;
set_cur_and_def_value<bool>(val, false, setv, data);
2022-06-15 03:04:40 +00:00
}
}
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;
set_cur_and_def_value<bool>(val, false, setv, data);
2022-06-15 03:04:40 +00:00
}
}
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, VAL_LIMIT_NONE, data);
2022-06-15 03:04:40 +00:00
}
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, VAL_LIMIT_ENUM, data))
2022-06-15 03:04:40 +00:00
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, VAL_LIMIT_NONE, data);
2022-06-15 03:04:40 +00:00
}
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, VAL_LIMIT_NONE, data);
2022-06-15 03:04:40 +00:00
}
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, def = SANE_FALSE;
2022-09-12 06:45:07 +00:00
SANE_Int after = 0;
if (setv)
{
if (is_erase_hole_l_id_ != -1)
{
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)is_erase_hole_l_id_, &yes);
hg_sane_middleware::instance()->get_def_value(handle_, (void*)is_erase_hole_l_id_, &def);
}
2022-09-12 06:45:07 +00:00
if (!yes && is_erase_hole_r_id_ != -1)
{
hg_sane_middleware::instance()->get_cur_value(handle_, (void*)is_erase_hole_r_id_, &yes);
hg_sane_middleware::instance()->get_def_value(handle_, (void*)is_erase_hole_r_id_, &def);
}
2022-09-12 06:45:07 +00:00
set_cur_and_def_value<bool>(yes == SANE_TRUE, def == SANE_TRUE, setv, data);
2022-09-12 06:45:07 +00:00
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_, (void*)is_erase_hole_l_id_, SANE_ACTION_SET_VALUE, &yes, &after);
2022-09-12 06:45:07 +00:00
yes = *(bool*)data ? SANE_TRUE : SANE_FALSE;
if (is_erase_hole_r_id_ != -1)
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)is_erase_hole_r_id_, SANE_ACTION_SET_VALUE, &yes, &after);
2022-09-12 06:45:07 +00:00
}
}
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, def = .0f;
2022-09-12 06:45:07 +00:00
if (setv)
{
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (void*)base_id);
void* init = hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id),
* cur = hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id);
float n = SANE_UNFIX(*(SANE_Fixed*)cur),
d = SANE_UNFIX(*(SANE_Fixed*)init);
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
2022-09-12 06:45:07 +00:00
{
float l = SANE_UNFIX(desc->constraint.range->min),
u = SANE_UNFIX(desc->constraint.range->max),
s = SANE_UNFIX(desc->constraint.range->quant);
set_value_range<SANE_Fixed, float>(*(SANE_Fixed*)cur, *(SANE_Fixed*)init, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setv, data, &scanner::to_float);
2022-09-12 06:45:07 +00:00
}
else
set_cur_and_def_value<float>(n, d, setv, data);
local_utility::free_memory(init);
local_utility::free_memory(cur);
2022-09-12 06:45:07 +00:00
ret = SCANNER_ERR_OK;
}
else
{
rv = (double)*(float*)data;
val = SANE_FIX(rv);
2022-09-12 06:45:07 +00:00
if (search_hole_range_l_id_ != -1)
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)search_hole_range_l_id_, SANE_ACTION_SET_VALUE, &val, &after);
val = SANE_FIX(rv);
2022-09-12 06:45:07 +00:00
if (search_hole_range_r_id_ != -1)
ret = hg_sane_middleware::instance()->set_option(handle_, (void*)search_hole_range_r_id_, SANE_ACTION_SET_VALUE, &val, &after);
2022-09-12 06:45:07 +00:00
}
}
return ret;
}
2022-06-15 03:04:40 +00:00
// ISaneInvoker
COM_API_IMPLEMENT(scanner, int, start(void))
2022-06-15 03:04:40 +00:00
{
2022-06-18 08:48:41 +00:00
int ret = SANE_STATUS_GOOD;
ev_cnt_ = 0;
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;
user_cancel_ = false;
2023-05-26 07:17:15 +00:00
fetch_imgs_ = 0;
is_scanning_ = true;
app_wnd_ = setting_.get() ? setting_->hwnd() : callback::find_main_wnd();
if (thread_starting_.get() && thread_starting_->joinable())
thread_starting_->join();
#ifdef START_SCAN_IN_THREAD
thread_starting_.reset(new std::thread(&scanner::thread_start, this));
#else
ret = thread_start();
#endif
2022-06-15 03:04:40 +00:00
return ret;
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, int, stop(void))
{
user_cancel_ = true;
2022-06-15 03:04:40 +00:00
return hg_sane_middleware::instance()->stop(handle_);
}
COM_API_IMPLEMENT(scanner, int, get_event(void))
2022-06-15 03:04:40 +00:00
{
return events_.take();
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, void, set_event_callback(int(__stdcall* handle_ev)(int, void*), void* para))
{
scanner_ev_handler_ = handle_ev;
evh_param_ = para;
}
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();
DWORD elapse = 2;
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);
}
else
Sleep(elapse);
count = images_.count();
//int ev = get_event();
//
//if (ev == SANE_EVENT_SCAN_FINISHED)
//{
// 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 00:54:01 +00:00
if (milliseconds != -1)
2022-06-15 03:04:40 +00:00
{
if (milliseconds <= elapse)
2022-06-15 03:04:40 +00:00
break;
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);
2023-05-20 04:02:26 +00:00
log_info(msg, 1);
2022-09-19 06:16:34 +00:00
}
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
{
scanned_img* img = images_.take(false);
2022-06-15 03:04:40 +00:00
2023-08-03 01:47:58 +00:00
if (img)
{
img->prepare_data_for_transfer(xfer);
img->add_ref();
2023-08-03 01:47:58 +00:00
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"Begin transferring image %d of %p\r\n", fetch_imgs_ + 1, img);
log_info(msg, 1);
}
2022-06-15 03:04:40 +00:00
return dynamic_cast<IScanImg*>(img);
}
2022-11-06 08:49:30 +00:00
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header, size_t* bytes, int* dpi))
2022-06-15 03:04:40 +00:00
{
2022-11-06 08:49:30 +00:00
return images_.get_header(header, bytes, dpi);
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, bool, discard_first_image(void))
{
scanned_img* img = images_.take();
if (img)
{
img->release();
return true;
}
else
{
return false;
}
}
2022-06-15 03:04:40 +00:00
COM_API_IMPLEMENT(scanner, bool, is_online(void))
{
std::string sn("");
return handle_ && control_read_string(IO_CTRL_CODE_GET_SERIAL, sn) != SCANNER_ERR_DEVICE_NOT_FOUND;
2022-06-15 03:04:40 +00:00
}
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, int, last_error(void))
{
return err_;
}
2023-05-26 07:17:15 +00:00
COM_API_IMPLEMENT(scanner, int, image_fetched(IScanImg* tx))
{
fetch_imgs_++;
if (ui_notify)
ui_notify(SANE_EVENT_IMG_UPLOADED, NULL, fetch_imgs_);
else if (indicator_.get())
indicator_->notify_data_arrived(false);
2023-08-03 01:47:58 +00:00
{
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"Transferring image %d of %p finished.\r\n", fetch_imgs_, tx);
log_info(msg, 1);
}
2023-05-26 07:17:15 +00:00
return 0;
}
2022-06-15 03:04:40 +00:00
COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes))
{
#define SIMPLE_STR_INFO(id, rdo) \
if (sn == id) \
{ \
if (type) \
*type = VAL_TYPE_STR; \
if (limit) \
*limit = rdo ? VAL_LIMIT_READONLY : VAL_LIMIT_NONE; \
if (bytes) \
*bytes = 255; \
\
return true; \
}
#define SIMPLE_INT_INFO(id, rdo) \
if (sn == id) \
{ \
if (type) \
*type = VAL_TYPE_INT; \
if (limit) \
*limit = rdo ? VAL_LIMIT_READONLY : VAL_LIMIT_NONE; \
if (bytes) \
*bytes = sizeof(int); \
\
return true; \
}
SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_VERSION, true);
SIMPLE_STR_INFO(SANE_OPT_ID_MANUFACTURER, true);
SIMPLE_STR_INFO(SANE_OPT_ID_COPYRIGHT, true);
SIMPLE_STR_INFO(SANE_OPT_ID_CO_URL, true);
SIMPLE_STR_INFO(SANE_OPT_ID_CO_TEL, true);
SIMPLE_STR_INFO(SANE_OPT_ID_CO_ADDR, true);
SIMPLE_STR_INFO(SANE_OPT_ID_CO_GPS, true);
SIMPLE_STR_INFO(SANE_OPT_ID_DEV_NAME, true);
SIMPLE_STR_INFO(SANE_OPT_ID_DEV_FAMILY, true);
SIMPLE_STR_INFO(SANE_OPT_ID_LOGIN, false);
SIMPLE_STR_INFO(SANE_OPT_ID_LOGOUT, false);
SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_LOG, false);
SIMPLE_STR_INFO(SANE_OPT_ID_DEVICE_LOG, false);
SIMPLE_STR_INFO(SANE_OPT_ID_DEVICE_MAC_ADDR, true);
2023-06-17 05:29:39 +00:00
SIMPLE_STR_INFO(SANE_OPT_ID_MOTOR_VER, true);
SIMPLE_INT_INFO(SANE_OPT_ID_HELP, false);
SIMPLE_INT_INFO(SANE_OPT_ID_HISTORY_COUNT, true);
SIMPLE_INT_INFO(SANE_OPT_ID_ROLLER_COUNT, false);
SIMPLE_INT_INFO(SANE_OPT_ID_VID, true);
SIMPLE_INT_INFO(SANE_OPT_ID_PID, true);
SIMPLE_INT_INFO(SANE_OPT_ID_ROLLER_LIFE, true);
sn = transfer_id(sn);
if (sn == -1)
return false;
2022-10-14 02:11:43 +00:00
EXAPIPOS ex = find_ex_api(sn);
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, ex == ex_opts_.end() ? (void*)sn : (void*)ex->base_ind);
2022-06-15 03:04:40 +00:00
bool ret = false;
if (desc)
{
if (type)
*type = scanner::from_sane_type(desc->type);
if (limit)
{
int lmt = scanner::from_sane_constraint(desc->constraint_type);
if (IS_CAP_READONLY(desc->cap))
lmt |= VAL_LIMIT_READONLY;
*limit = (value_limit)lmt;
}
2022-06-15 03:04:40 +00:00
if (bytes)
*bytes = desc->size;
ret = true;
}
return ret;
}
COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* param))
{
if (sane_ids_.count((sane_option_id)sn) &&
sane_ids_[(sane_option_id)sn] == sn)
{
char buf[256] = { 0 };
value_type type = VAL_TYPE_NONE;
int ret = hg_sane_middleware::instance()->set_option(handle_, (void*)sn, SANE_ACTION_GET_VALUE, buf, NULL);
if (ret == SANE_STATUS_GOOD)
{
get_option_info(sn, &type, NULL, NULL);
if (type == VAL_TYPE_STR)
{
std::string str(buf);
setval(&str, VAL_ROLE_CURRENT, VAL_LIMIT_NONE, param);
}
else
setval(buf, VAL_ROLE_CURRENT, VAL_LIMIT_NONE, param);
return true;
}
return false;
}
int org_id = sn;
if(sn == 0x102c) // CapType::Language
sn = transfer_id(SANE_OPT_ID_LANGUAGE);
else
sn = transfer_id(sn);
if (sn == -1)
return false;
2022-06-15 03:04:40 +00:00
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_, (void*)sn);
void* init = hg_sane_middleware::instance()->get_def_value(handle_, (void*)sn);
2022-06-15 03:04:40 +00:00
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_, (void*)sn, &v);
2022-06-15 03:04:40 +00:00
val = v == SANE_TRUE;
//set_cur_and_def_value<bool>(val, *(SANE_Bool*)init == SANE_TRUE, setval, param);
{
int role = VAL_ROLE_NONE;
val = false;
if (*(SANE_Bool*)init == SANE_FALSE)
role |= VAL_ROLE_DEFAULT;
if (v == SANE_FALSE)
role |= VAL_ROLE_CURRENT;
setval(&val, (value_role)role, VAL_LIMIT_ENUM, param);
val = true;
role = VAL_ROLE_NONE;
if (*(SANE_Bool*)init == SANE_TRUE)
role |= VAL_ROLE_DEFAULT;
if (v == SANE_TRUE)
role |= VAL_ROLE_CURRENT;
setval(&val, (value_role)role, VAL_LIMIT_ENUM, param);
}
2022-06-15 03:04:40 +00:00
}
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_, (void*)sn, &cur);
2022-06-15 03:04:40 +00:00
val = cur;
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, VAL_LIMIT_ENUM, param))
2022-06-15 03:04:40 +00:00
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_, (void*)sn, &cur);
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]);
if (!setval(&val, role, VAL_LIMIT_ENUM, param))
2022-06-15 03:04:40 +00:00
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_, (void*)sn, buf);
2022-06-15 03:04:40 +00:00
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 (org_id == 0x102c)
{
// const char* hz = local_trans::lang_trans_between_hz936(val.c_str(), false, NULL);
int lid = sane_opt_trans::language_to_twain(val.c_str());
if (!setval(&lid, role, VAL_LIMIT_ENUM, param))
break;
}
else if (!setval(&val, role, VAL_LIMIT_ENUM, param))
2022-06-15 03:04:40 +00:00
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, bool, get_value(int sn, void* data, int* len))
{
if (sn != SANE_OPT_ID_DRIVER_LOG && sn != SANE_OPT_ID_DEVICE_LOG)
return false;
SANE_Status ret = hg_sane_middleware::instance()->set_option(handle_, (const void*)sn, SANE_ACTION_GET_VALUE, data, NULL);
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"get log of(%x) = 0x%x\r\n", sn, ret);
log_info(msg, 1);
return ret == SANE_STATUS_GOOD;
}
2022-06-15 03:04:40 +00:00
COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val))
{
if (sane_ids_.count((sane_option_id)sn) &&
sane_ids_[(sane_option_id)sn] == sn)
{
int ret = hg_sane_middleware::instance()->set_option(handle_, (void*)sn, SANE_ACTION_SET_VALUE, val, NULL);
2023-05-16 07:38:54 +00:00
return ret;
}
int org_id = sn;
if (sn == 0x102c) // CapType::Language
sn = transfer_id(SANE_OPT_ID_LANGUAGE);
else
sn = transfer_id(sn);
if (sn == -1)
return SANE_STATUS_UNSUPPORTED;
2022-06-15 03:04:40 +00:00
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_, (void*)sn);
2022-06-15 03:04:40 +00:00
2022-09-23 08:47:00 +00:00
{
2022-11-19 00:48:39 +00:00
wchar_t msg[256] = { 0 };
2022-10-07 09:51:09 +00:00
if (ex == ex_opts_.end())
2022-11-19 00:48:39 +00:00
swprintf_s(msg, _countof(msg) - 1, L"set_value of %s(%s) of ID %d\r\n", local_trans::a2u(desc->name, CP_UTF8).c_str(), local_trans::a2u(hg_sane_middleware::option_value_2_string(desc->type, val).c_str(), CP_UTF8).c_str(), sn);
else if(ex->base_ind != -1)
2022-11-19 00:48:39 +00:00
{
desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (void*)ex->base_ind);
2022-11-19 00:48:39 +00:00
swprintf_s(msg, _countof(msg) - 1, L"set_value of %s(0x%x) of ID %d, base id = %d)\r\n", local_trans::a2u(desc->name, CP_UTF8).c_str(), *(unsigned*)val, sn, ex->base_ind);
}
2022-09-23 08:47:00 +00:00
log_info(msg, 0);
}
twain_set_ = true;
2022-06-15 03:04:40 +00:00
if (ex == ex_opts_.end())
{
std::string strv("");
void* w = val;
if (org_id == 0x102c)
{
// const char* str = sane_opt_trans::language_from_twain(*(int*)val);
strv = sane_opt_trans::language_from_twain(*(int*)val);
w = &strv;
}
if (!set_option_value_with_parent(sn, w, &ret))
ret = set_option_value(sn, desc->type, desc->size, w);
2022-06-15 03:04:40 +00:00
ret = local_utility::sane_statu_2_scanner_err(ret);
}
else
{
ret = (this->*ex->ex_api)(ex->base_ind, val, NULL);
}
if (sn == resolution_id_)
{
if (desc->type == SANE_TYPE_FIXED)
2022-07-18 02:55:01 +00:00
dpi_ = (int)(*(float*)val + .5f);
else
dpi_ = *(int*)val;
}
2022-06-15 03:04:40 +00:00
return ret;
}
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);
}
COM_API_IMPLEMENT(scanner, int, get_fixed_ids(bool(__stdcall* cb)(uint32_t id, void* param), void* param))
{
for (auto& v : sane_ids_)
{
if (!cb(v.first, param))
break;
}
return 0;
}
2022-06-15 03:04:40 +00:00
// SANE options ID ...
SANE_OPTION_ID_IMPLEMENT(color_correction)
SANE_OPTION_ID_IMPLEMENT(fold_type)
2022-06-15 03:04:40 +00:00
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)
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-10-24 08:58:09 +00:00
SANE_OPTION_ID_IMPLEMENT(fold_direction)
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))
{
int ret = SCANNER_ERR_NO_DATA;
if (callback::get_config_content)
2022-07-01 07:24:58 +00:00
{
char* cont = callback::get_config_content(local_trans::u2a(scanner_name_.c_str(), CP_UTF8).c_str(), NULL);
if (cont)
{
if (*len <= strlen(cont))
{
*len = strlen(cont) + 4;
ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
}
else
{
strcpy(buf, cont);
ret = SCANNER_ERR_OK;
*len = strlen(cont);
}
if (callback::twain_ui_free)
callback::twain_ui_free(cont);
}
2022-07-01 07:24:58 +00:00
}
return ret;
2022-07-01 07:24:58 +00:00
}
COM_API_IMPLEMENT(scanner, int, twain_set_config(char* buf, size_t len))
{
if(callback::apply_given_config)
2022-07-01 07:24:58 +00:00
{
if(callback::apply_given_config(buf, handle_, &sane_api_) == 0)
return SCANNER_ERR_OK;
2022-07-01 07:24:58 +00:00
}
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
}
COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bool indicator))
2022-06-15 03:04:40 +00:00
{
is_show_ui_ = with_scan;
is_show_setting_ = true;
events_.clear();
if (callback::show_setting_ui)
{
2023-05-08 14:29:50 +00:00
if (with_scan)
{
images_.clear();
scan_msg_ = "OK";
scan_err_ = false;
}
2023-05-05 09:53:46 +00:00
auto ui = [this](ui_result res)
{
2023-05-05 09:53:46 +00:00
int uev = SANE_EVENT_SCAN_FINISHED;
switch (res)
{
case UI_RESULT_FAILED:
break;
case UI_RESULT_OK:
2023-05-05 09:53:46 +00:00
break;
case UI_RESULT_CLOSE_NORMAL:
2023-05-18 09:00:35 +00:00
is_show_ui_ = false;
uev = SANE_EVENT_UI_CLOSE_NORMAL;
on_ui_event(uev, (void*)uev);
break;
2023-05-05 09:53:46 +00:00
case UI_RESULT_CLOSE_CANCEL:
is_show_ui_ = false;
2023-05-18 09:00:35 +00:00
uev = SANE_EVENT_UI_CLOSE_CANCEL;
on_ui_event(uev, (void*)uev);
break;
case UI_RESULT_CLOSE_SETTING:
is_show_setting_ = false;
uev = SANE_EVENT_UI_CLOSE_SETTING;
on_ui_event(uev, (void*)uev);
2023-05-05 09:53:46 +00:00
break;
case UI_RESULT_START_SCAN:
on_ui_event(SANE_EVENT_UI_SCAN_COMMAND, NULL);
break;
default:
break;
}
};
int res = callback::show_setting_ui(handle_, parent, &sane_api_, local_trans::u2a(scanner_name_.c_str(), CP_UTF8).c_str(),with_scan, ui);
//if (res == ui_result::UI_RESULT_CLOSE_NORMAL)
//{
2023-05-05 09:53:46 +00:00
// int ev = SANE_EVENT_UI_CLOSE_NORMAL;
// on_ui_event(ev, (void*)ev);
//}
//else if (res == ui_result::UI_RESULT_START_SCAN)
//{
// //callback::show_progress_ui(parent, ui_process, &ui_notify);
// //start();
// on_ui_event(SANE_EVENT_UI_SCAN_COMMAND, NULL);
//}
//else if (res == UI_RESULT_CLOSE_CANCEL)
//{
// int ev = SANE_EVENT_UI_CLOSE_CANCEL;
// on_ui_event(ev, (void*)ev);
//}
//on_ui_event(ev, NULL);
}
else if (cfg_)
{
if (with_scan)
{
events_.clear();
images_.clear();
scan_msg_ = "OK";
scan_err_ = false;
}
size_t pid = scanner_name_.find(L" - ");
if (pid == -1)
pid = scanner_name_.length();
setting_.reset(new dlg_setting(parent, &sane_api_, handle_, with_scan, scanner_name_.substr(0, pid).c_str()));
setting_->set_ui_event_notify(&scanner::ui_callback, this);
setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this, &twain_set_);
indicator_.reset();
if (indicator)
{
indicator_.reset(new dlg_indicator(setting_->hwnd()));
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
}
setting_->show(true);
2022-06-27 01:38:12 +00:00
}
2022-06-18 08:48:41 +00:00
return true;
2022-06-15 03:04:40 +00:00
}
2023-04-24 09:23:43 +00:00
COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent, bool bIndicator))
2022-06-15 03:04:40 +00:00
{
is_bIndicator = bIndicator;
ui_notify = std::function<void(int, void*, int)>();
auto ui_process = [this](ui_result res)
{
int uev = SANE_EVENT_SCAN_FINISHED;
switch (res)
{
case UI_RESULT_CLOSE_NORMAL:
uev = SANE_EVENT_UI_CLOSE_NORMAL;
//if (!is_show_ui_)
{
on_ui_event(uev, (void*)uev);
}
break;
case UI_RESULT_CLOSE_CANCEL:
uev = SANE_EVENT_UI_CLOSE_CANCEL;
//if (!is_show_ui_)
2023-05-11 13:07:00 +00:00
{
on_ui_event(uev, (void*)uev);
}
//else
// stop();
break;
default:
break;
}
};
if (callback::show_progress_ui && bIndicator)
{
2023-04-23 14:23:02 +00:00
callback::show_progress_ui(parent, ui_process,&ui_notify);
}
else if(bIndicator)
{
if (setting_.get() && IsWindowVisible(setting_->hwnd()))
parent = setting_->hwnd();
else if (!IsWindow(parent))
parent = callback::find_main_wnd();
indicator_.reset(new dlg_indicator(parent));
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
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();
if (setting_.get())
setting_.reset();
2023-05-19 07:03:38 +00:00
if (callback::close_ui)
2023-05-23 08:16:30 +00:00
callback::close_ui(UI_INDICATOR | UI_SETTING | UI_MSG_BOX);
is_show_setting_ = false;
ui_notify = std::function<void(int, void*, int)>();
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 ...
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)
{
img_ind_ = 0;
if (indicator_.get())
indicator_->notify_working();
else if (callback::show_progress_ui && is_bIndicator)
ui_notify(ev_code, data, *len);
on_ui_event(ev_code, (void*)ev_code);
2023-05-20 04:02:26 +00:00
log_info(L"Scanning ...\r\n", 1);
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-11-06 08:49:30 +00:00
img = new scanned_img(handle_, simg->header, simg->data, simg->bytes, simg->flag.dpi, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
2022-06-29 08:13:05 +00:00
if (img->bytes() /*>= simg->bytes*/)
2022-06-18 00:54:01 +00:00
{
size_t bytes = 0;
int times = 0;
images_.count(&bytes);
2022-09-20 10:14:27 +00:00
img->set_image_status((SANE_Image_Statu)simg->flag.statu);
bytes /= 1024 * 1024;
while (bytes > max_img_mem_ && !user_cancel_ && times++ < 20) // memory control
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
images_.count(&bytes);
bytes /= 1024 * 1024;
if (times == 1)
2023-05-20 04:02:26 +00:00
log_info(L"Memory usage upto limit! wait up to 100 ms ...\r\n", 1);
}
images_.save(img, img->bytes());
2022-06-18 00:54:01 +00:00
}
else
{
img->release();
}
if (indicator_.get())
indicator_->notify_data_arrived(true);
else if (ui_notify)
ui_notify(ev_code, data, img_ind_);
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);
2023-05-20 04:02:26 +00:00
log_info(msg, 1);
2022-09-19 06:16:34 +00:00
}
2022-06-18 08:48:41 +00:00
}
else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED)
{
2023-05-26 07:17:15 +00:00
//if (indicator_.get())
// indicator_->notify_data_arrived(false);
//else if (ui_notify)
// ui_notify(ev_code, data, 0);
2022-06-18 00:54:01 +00:00
}
else if (ev_code == SANE_EVENT_SCAN_FINISHED)
{
err_ = *len;
if (indicator_.get())
indicator_->notify_scan_over((char*)data, *len != SCANNER_ERR_OK);
else if (ui_notify)
ui_notify(ev_code, data, *len);
else
{
if (*len)
{
if (callback::show_messagebox_ui)
{
callback::show_messagebox_ui(app_wnd_, ev_code, (void*)data, 0);
}
else // windows message box ...
{
std::wstring msg(local_trans::a2u((char*)data, CP_UTF8));
if (!IsWindow(app_wnd_))
callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str());
MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str(), MB_OK);
}
}
2023-05-05 01:47:34 +00:00
on_ui_event(ev_code, (void*)ev_code);
}
// is_scanning_ = false;
2023-04-23 14:23:02 +00:00
2022-09-19 06:16:34 +00:00
{
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"Scan finished with error: %u\r\n", *len);
2023-05-20 04:02:26 +00:00
log_info(msg, 1);
2022-09-19 06:16:34 +00:00
}
2022-06-18 00:54:01 +00:00
}
2023-08-03 03:22:09 +00:00
//else if (ev_code == SANE_EVENT_ERROR) // 灞忚斀锛屽湪鍋滄鎵弿鏃跺睍绀轰俊鎭?- 2023-05-30
//{
// if (callback::show_messagebox_ui && *len)
// {
// callback::show_messagebox_ui(app_wnd_, ev_code, (void*)data, 0);
// }
2023-08-03 03:22:09 +00:00
// else if (*len) //閿欒寮瑰嚭
// {
// std::wstring msg(local_trans::a2u((char*)data, CP_UTF8));
// if (!IsWindow(app_wnd_))
// callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str());
// MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str(), MB_OK);
// }
//// on_ui_event(ev_code, (void*)ev_code);
//}
2022-06-18 00:54:01 +00:00
return 0;
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_;
std::string g_path_file_("");
2022-09-19 06:16:34 +00:00
FILE* g_file_ = NULL;
2023-05-20 04:02:26 +00:00
static int g_log_level = 1;
static int get_log_level(const char* log_file)
{
std::string cfg(log_file);
size_t pos = cfg.rfind('\\');
2022-09-19 06:16:34 +00:00
2023-05-20 04:02:26 +00:00
cfg.erase(pos);
pos = cfg.rfind('\\');
if (pos != std::string::npos)
{
if (stricmp(cfg.substr(pos).c_str(), "\\log") == 0)
{
cfg.erase(pos);
cfg += "\\config";
}
}
cfg += "\\debug.cfg";
2023-05-20 04:09:29 +00:00
return GetPrivateProfileIntA("log", "twain-level", 1, cfg.c_str());
2023-05-20 04:02:26 +00:00
}
2022-09-19 06:16:34 +00:00
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";
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";
g_file_ = fopen(path.c_str(), "a+b");
g_path_file_ = path;
2022-09-19 06:16:34 +00:00
}
if (g_file_)
{
fseek(g_file_, 0, SEEK_END);
if (ftell(g_file_))
{
2022-11-17 02:26:53 +00:00
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_);
}
2022-11-08 03:22:21 +00:00
wchar_t ts[128] = { 0 }, now[40] = { 0 };
hg_get_current_time_w(now);
2023-05-20 04:02:26 +00:00
g_log_level = get_log_level(g_path_file_.c_str());
swprintf_s(ts, _countof(ts) - 1, L"==================%s - %d, Proc %d==================\r\n", now, g_log_level, GetCurrentProcessId());
fwrite(ts, 2, lstrlenW(ts), g_file_);
2023-05-20 04:02:26 +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)
{
fclose(g_file_);
remove(g_path_file_.c_str());
g_file_ = fopen(g_path_file_.c_str(), "wb");
if (g_file_)
{
unsigned short bom = 0x0feff;
2022-11-08 03:22:21 +00:00
wchar_t ts[128] = { 0 }, now[40] = { 0 };
hg_get_current_time_w(now);
2022-11-08 03:22:21 +00:00
swprintf_s(ts, _countof(ts) - 1, L"==================%s (Truncated when size > 10MB) ==================\r\n", now);
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
2022-11-06 03:29:49 +00:00
extern "C"
{
2022-06-15 03:04:40 +00:00
#ifdef EXPORT_SANE_API
2022-11-06 03:29:49 +00:00
__declspec(dllexport)
2022-06-15 03:04:40 +00:00
#else
2022-11-06 03:29:49 +00:00
__declspec(dllimport)
2022-06-15 03:04:40 +00:00
#endif
2022-11-06 03:29:49 +00:00
int __stdcall initialize(void* reserve)
{
init_log();
callback::init_ui();
2022-11-06 03:29:49 +00:00
hg_sane_middleware::set_callback(callback::sane_event_callback, NULL);
if (hg_sane_middleware::instance()->is_ready())
return SANE_STATUS_GOOD;
else
return SCANNER_ERR_LANG_PAK_LOST;
2022-11-06 03:29:49 +00:00
}
2022-06-15 03:04:40 +00:00
#ifdef EXPORT_SANE_API
2022-11-06 03:29:49 +00:00
__declspec(dllexport)
2022-06-15 03:04:40 +00:00
#else
2022-11-06 03:29:49 +00:00
__declspec(dllimport)
2022-06-15 03:04:40 +00:00
#endif
int __stdcall open_scanner(SCANNERID scanner_id, ISaneInvoker** invoker, bool last_try)
2022-11-06 03:29:49 +00:00
{
if (!invoker)
return SCANNER_ERR_INVALID_PARAMETER;
2022-06-15 03:04:40 +00:00
2022-11-06 03:29:49 +00:00
if (!is_scanner_online(scanner_id))
{
if (last_try)
{
HWND parent = callback::find_main_wnd();
std::string msg(callback::language_trans("\xE6\xB2\xA1\xE6\x9C\x89\xE6\x89\xBE\xE5\x88\xB0\xE6\x89\xAB\xE6\x8F\x8F\xE4\xBB\xAA\xEF\xBC\x81", true, NULL)),
title(callback::language_trans("\xE9\x94\x99\xE8\xAF\xAF", true, NULL));
if (callback::show_messagebox_ui)
callback::show_messagebox_ui(parent, 0, &msg[0], SCANNER_ERR_DEVICE_NOT_FOUND);
else
MessageBoxW(parent, local_trans::a2u(msg.c_str(), CP_UTF8).c_str(), local_trans::a2u(title.c_str(), CP_UTF8).c_str(), MB_OK);
}
2022-11-06 03:29:49 +00:00
return SCANNER_ERR_DEVICE_NOT_FOUND;
}
2022-06-15 03:04:40 +00:00
2022-11-06 03:29:49 +00:00
scanner* scn = new scanner(scanner_id);
if (scn->last_error() == SCANNER_ERR_OK)
{
*invoker = dynamic_cast<ISaneInvoker*>(scn);
2022-06-15 03:04:40 +00:00
2022-11-06 03:29:49 +00:00
return 0;
}
else
{
int ret = scn->last_error();
2022-11-06 03:29:49 +00:00
scn->release();
*invoker = NULL;
if (last_try)
{
HWND parent = callback::find_main_wnd();
std::string msg(callback::language_trans("\xE6\x89\x93\xE5\xBC\x80\xE6\x89\xAB\xE6\x8F\x8F\xE4\xBB\xAA\xE5\xA4\xB1\xE8\xB4\xA5\xE3\x80\x82", true, NULL)),
title(callback::language_trans("\xE9\x94\x99\xE8\xAF\xAF", true, NULL));
if (callback::show_messagebox_ui)
callback::show_messagebox_ui(parent, 0, &msg[0], ret);
else
MessageBoxW(parent, local_trans::a2u(msg.c_str(), CP_UTF8).c_str(), local_trans::a2u(title.c_str(), CP_UTF8).c_str(), MB_OK);
}
2022-11-06 03:29:49 +00:00
return ret;
}
}
2022-06-15 03:04:40 +00:00
#ifdef EXPORT_SANE_API
2022-11-06 03:29:49 +00:00
__declspec(dllexport)
2022-06-15 03:04:40 +00:00
#else
2022-11-06 03:29:49 +00:00
__declspec(dllimport)
2022-06-15 03:04:40 +00:00
#endif
2022-11-06 03:29:49 +00:00
bool __stdcall is_scanner_online(SCANNERID scanner_id)
{
std::vector<std::string> que;
2022-11-06 03:29:49 +00:00
scanner::get_scanner_name(scanner_id, que);
return !que.empty();
}
2022-06-15 03:04:40 +00:00
#ifdef EXPORT_SANE_API
2022-11-06 03:29:49 +00:00
__declspec(dllexport)
2022-06-15 03:04:40 +00:00
#else
2022-11-06 03:29:49 +00:00
__declspec(dllimport)
2022-06-15 03:04:40 +00:00
#endif
2022-11-06 03:29:49 +00:00
int __stdcall uninitialize(void* reserve)
{
hg_sane_middleware::set_callback(NULL, NULL);
hg_sane_middleware::clear();
close_log();
2023-05-20 04:02:26 +00:00
callback::unint_ui();
2022-06-15 03:04:40 +00:00
2022-11-06 03:29:49 +00:00
return 0;
}
2022-09-19 06:16:34 +00:00
#ifdef EXPORT_SANE_API
2022-11-06 03:29:49 +00:00
__declspec(dllexport)
2022-09-19 06:16:34 +00:00
#else
2022-11-06 03:29:49 +00:00
__declspec(dllimport)
2022-09-19 06:16:34 +00:00
#endif
2022-11-06 03:29:49 +00:00
void __stdcall log_info(const wchar_t* info, int level)
{
2023-05-20 04:02:26 +00:00
if(level >= g_log_level)
log(info);
2022-11-06 03:29:49 +00:00
}
2022-06-15 03:04:40 +00:00
2022-11-06 03:29:49 +00:00
}