code_twain/sane/scanner.cpp

2054 lines
56 KiB
C++
Raw Normal View History

2022-06-15 03:04:40 +00:00
#include "scanner.h"
#include <Windows.h>
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include <sane/sane_option_definitions.h>
#include "../../code_device/hgsane/sane_hg_mdw.h"
#include "sane_option_trans.h"
#include <chrono>
2022-06-18 00:54:01 +00:00
#include <mutex>
2022-06-18 08:48:41 +00:00
#include "DlgIndicator.h"
#include "DlgSetting.h"
2022-06-15 03:04:40 +00:00
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
#define SET_SANE_OPT_ID(id, id_name, title, val, extension) \
if(compare_sane_opt(OPTION_TITLE_##title, val)) \
{ \
id_name##_id_ = id; \
extension(id); \
}
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);
}
2022-06-18 00:54:01 +00:00
namespace callback
{
static std::mutex cb_lock_;
typedef struct _scanner_inst
{
SANE_Handle dev;
scanner* invoker;
bool operator==(const SANE_Handle& h)
{
return dev == h;
}
bool operator==(const scanner* obj)
{
return invoker == obj;
}
}SCNINST;
std::vector<SCNINST> g_scanner_instances;
int sane_event_callback( // 注册回调的对象,需要保证该回调是多线程安全的
SANE_Handle hdev // 产生事件的设备句柄
, int code // 回调事件代码
, void* data // 回调事件数据,根据事件代码有所不同,参照具体事件定义
, unsigned int* len // 数据长度字节或者event_data的缓冲区长度详细请看相应的事件代码
, void* param // 用户自定义数据与调用sane_init_ex传入时的保持一致
) // 返回值依不同的事件代码而定通常为“0”
{
std::lock_guard<std::mutex> lock(cb_lock_);
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), hdev);
if (it != g_scanner_instances.end())
return it->invoker->handle_event(code, data, len);
else
return 0;
}
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-06-15 03:04:40 +00:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// class scanner
scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
2022-06-18 00:54:01 +00:00
, dpi_(200), tmp_path_(L""), img_ind_(0), cb_invoker_(NULL), cb_param_(NULL), working_(false)
, ui_quit_(true), scanner_name_(L"")
2022-06-15 03:04:40 +00:00
{
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
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;
2022-06-15 03:04:40 +00:00
err_ = open();
}
scanner::~scanner()
2022-06-18 00:54:01 +00:00
{
callback::unreg_callback(this);
}
2022-06-15 03:04:40 +00:00
std::string scanner::get_scanner_name(SCANNERID id)
{
ScannerInfo* devs = NULL;
long count = 0;
std::string name("");
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
count++;
devs = new ScannerInfo[count];
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_OK)
{
for (int i = 0; i < count; ++i)
{
if (devs[i].vid == GET_SCANNER_VID(id) &&
devs[i].pid == GET_SCANNER_PID(id))
{
name = devs[i].name;
break;
}
}
}
delete[] devs;
}
return name;
}
value_type scanner::from_sane_type(SANE_Value_Type type)
{
if (type == SANE_TYPE_BOOL)
return VAL_TYPE_BOOL;
else if (type == SANE_TYPE_INT)
return VAL_TYPE_INT;
else if (type == SANE_TYPE_FIXED)
return VAL_TYPE_FLOAT;
else if (type == SANE_TYPE_STRING)
return VAL_TYPE_STR;
else
return VAL_TYPE_NONE;
}
value_limit scanner::from_sane_constraint(SANE_Constraint_Type type)
{
if (type == SANE_CONSTRAINT_RANGE)
return VAL_LIMIT_RANGE;
else if (type == SANE_CONSTRAINT_STRING_LIST || type == SANE_CONSTRAINT_WORD_LIST)
return VAL_LIMIT_ENUM;
else
return VAL_LIMIT_NONE;
}
int __stdcall scanner::to_int(SANE_Int v)
{
return v;
}
float __stdcall scanner::to_float(SANE_Fixed v)
{
return SANE_UNFIX(v);
}
2022-06-27 01:38:12 +00:00
void __stdcall scanner::ui_callback(ui_event uev, void* sender, void* param)
2022-06-18 08:48:41 +00:00
{
2022-06-27 01:38:12 +00:00
((scanner*)param)->on_ui_quit(uev, sender);
2022-06-18 08:48:41 +00:00
}
2022-06-15 03:04:40 +00:00
// IRef
COM_API_IMPLEMENT(scanner, long, add_ref(void))
{
return refer::add_ref();
}
COM_API_IMPLEMENT(scanner, long, release(void))
{
return refer::release();
}
2022-06-27 01:38:12 +00:00
void scanner::on_ui_quit(ui_event uev, void* sender)
2022-06-18 08:48:41 +00:00
{
2022-06-27 01:38:12 +00:00
switch (uev)
{
case UI_EVENT_CLOSE_CANCEL: // post from indicator
2022-06-18 08:48:41 +00:00
stop();
2022-06-27 01:38:12 +00:00
case UI_EVENT_CLOSE_NORMAL: // post from indicator & dlg_setting
if (sender == indicator_.get() && setting_.get())
{
setting_->hide();
setting_.reset();
}
else if (sender == setting_.get() && indicator_.get())
{
indicator_->hide();
indicator_.reset();
}
ui_quit_ = true;
break;
case UI_EVENT_BEGIN_SCANNING: // post from dlg_setting, so we show indicator ...
if (start() == SANE_STATUS_GOOD)
{
if (indicator_.get())
indicator_->show();
}
else
setting_->enable(true);
break;
default:
break;
}
2022-06-18 08:48:41 +00:00
if (cb_invoker_)
cb_invoker_(ui_quit_ ? SANE_EVENT_SCAN_FINISHED : SANE_EVENT_WORKING, NULL, NULL, cb_param_);
2022-06-18 08:48:41 +00:00
}
2022-06-15 03:04:40 +00:00
int scanner::open(void)
{
int ret = close();
std::string name(scanner::get_scanner_name(id_));
scanner_name_ = L"";
2022-06-15 03:04:40 +00:00
if (name.empty())
return SCANNER_ERR_DEVICE_NOT_FOUND;
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
if (ret == SANE_STATUS_GOOD)
{
scanner_name_ = local_trans::a2u(name.c_str(), CP_UTF8);
2022-06-18 00:54:01 +00:00
callback::reg_callback(handle_, this);
2022-06-15 03:04:40 +00:00
ret = init_options_id();
}
return ret;
}
int scanner::close(void)
{
if (handle_)
hg_sane_middleware::instance()->close_device(handle_);
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) \
SET_SANE_OPT_ID(op_id, var, predef, desc->title, func)
while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, op_id)))
{
SET_OPT_ID(is_multiout, DLSC, extension_none)
else SET_OPT_ID(multiout_type, DLSCLX, extension_multiout_type)
else SET_OPT_ID(color_mode, YSMS, extension_color_mode)
else SET_OPT_ID(erase_color, HDHHBTX_CS, extension_erase_color)
else SET_OPT_ID(erase_multiout_red, 24WCSTX_DLSCCH, extension_none)
else SET_OPT_ID(erase_paper_red, 24WCSTX_DTKCH, extension_none)
else SET_OPT_ID(is_erase_background, BJYC, extension_none)
else SET_OPT_ID(background_color_range, BJSCFDFW, extension_none)
else SET_OPT_ID(sharpen, RHYMH, extension_sharpen)
else SET_OPT_ID(erase_morr, QCMW, extension_none)
else SET_OPT_ID(erase_grids, CWW, extension_none)
else SET_OPT_ID(error_extend, CWKS, extension_none)
else SET_OPT_ID(is_noise_modify, HBTXZDYH, extension_none)
else SET_OPT_ID(noise_threshold, ZDYHCC, extension_none)
else SET_OPT_ID(paper, ZZCC, extension_paper)
else SET_OPT_ID(is_custom_area, ZDYSMQY, extension_none)
else SET_OPT_ID(curstom_area_l, SMQYZCmm, extension_none)
else SET_OPT_ID(curstom_area_r, SMQYYCmm, extension_none)
else SET_OPT_ID(curstom_area_t, SMQYSCmm, extension_none)
else SET_OPT_ID(curstom_area_b, SMQYXCmm, extension_none)
else SET_OPT_ID(is_size_check, CCJC, extension_none)
else SET_OPT_ID(page, SMYM, extension_page)
else SET_OPT_ID(blank_page_threshold, TGKBYLMD, extension_none)
else SET_OPT_ID(resolution, FBL, extension_none)
else SET_OPT_ID(image_quality, HZ, extension_none)
else SET_OPT_ID(is_swap, JHZFM, extension_none)
else SET_OPT_ID(is_split, TXCF, extension_none)
else SET_OPT_ID(is_auto_deskew, ZDJP, extension_none)
else SET_OPT_ID(is_custom_gamma, QYSDQX, extension_none)
else SET_OPT_ID(bright, LDZ, extension_none)
else SET_OPT_ID(contrast, DBD, extension_none)
else SET_OPT_ID(gamma, JMZ, extension_none)
else SET_OPT_ID(is_erase_black_frame, XCHK, extension_none)
else SET_OPT_ID(deep_sample, SSYZ, extension_none)
else SET_OPT_ID(threshold, YZ, extension_none)
else SET_OPT_ID(anti_noise, BJKZDJ, extension_none)
else SET_OPT_ID(margin, BYSJ, extension_none)
else SET_OPT_ID(fill_background, BJTCFS, extension_fill_bkg_method)
else SET_OPT_ID(is_anti_permeate, FZST, extension_none)
else SET_OPT_ID(anti_permeate_level, FZSTDJ, extension_none)
else SET_OPT_ID(is_erase_hole, CKYC, extension_none)
else SET_OPT_ID(search_hole_range, CKSSFWZFMBL, extension_none)
else SET_OPT_ID(is_filling_color, SCTC, extension_none)
else SET_OPT_ID(is_ultrasonic_check, CSBJC, extension_none)
else SET_OPT_ID(is_check_staple, ZDJC, extension_none)
else SET_OPT_ID(scan_mode, SMZS, extension_none)
else SET_OPT_ID(scan_count, SMSL, extension_none)
else SET_OPT_ID(text_direction, WGFX, extension_text_direction)
else SET_OPT_ID(is_rotate_bkg180, BMXZ180, extension_none)
else SET_OPT_ID(is_check_dogear, ZJJC, extension_none)
else SET_OPT_ID(dogear_size, ZJDX, extension_none)
else SET_OPT_ID(is_check_skew, WXJC, extension_none)
else SET_OPT_ID(skew_range, WXRRD, extension_none)
else SET_OPT_ID(black_white_threshold, HBTXYZ, extension_none)
2022-06-15 03:04:40 +00:00
op_id++;
}
#define EX_APPENDIX_API(name) \
{ \
EXAPI ea; \
ea.ind = ex_##name##_id_ = ex_id_++; \
ea.ex_api = &scanner::handle_ex_##name; \
ex_opts_.push_back(ea); \
}
EX_APPENDIX_API(final_compression);
EX_APPENDIX_API(final_format);
EX_APPENDIX_API(serial);
EX_APPENDIX_API(to_be_scan);
EX_APPENDIX_API(scan_with_hole);
EX_APPENDIX_API(device_code);
EX_APPENDIX_API(power);
EX_APPENDIX_API(hardware_version);
EX_APPENDIX_API(ip);
if (black_white_threshold_id_ == -1)
black_white_threshold_id_ = 0x8836;
2022-06-15 03:04:40 +00:00
return ret;
}
int scanner::control_read_string(int code, std::string& ret)
{
char* buf = NULL;
unsigned len = 0;
int err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
ret = "";
if (err == SANE_STATUS_NO_MEM)
{
len += 4;
buf = new char[len];
memset(buf, 0, len);
err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
if (err == SANE_STATUS_GOOD)
ret = buf;
delete[] buf;
}
return err;
}
void scanner::extension_none(int id)
{
}
void scanner::extension_multiout_type(int id)
{
EXAPI ea;
ex_multiout_type_id_ = ex_id_++;
ea.ind = ex_multiout_type_id_;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_multiout;
ex_opts_.push_back(ea);
}
void scanner::extension_color_mode(int id)
{
EXAPI ea;
ea.ind = ex_color_mode_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_color_mode;
ex_opts_.push_back(ea);
ex_auto_color_type_id_ = ex_id_++;
ea.base_ind = id;
ea.ind = ex_auto_color_type_id_;
ea.ex_api = &scanner::handle_ex_auto_color_type;
ex_opts_.push_back(ea);
}
void scanner::extension_sharpen(int id)
{
EXAPI ea;
ex_sharpen_id_ = ex_id_++;
ea.base_ind = id;
ea.ind = ex_sharpen_id_;
ea.ex_api = &scanner::handle_ex_sharpen;
ex_opts_.push_back(ea);
}
void scanner::extension_paper(int id)
{
EXAPI ea;
ea.ind = ex_paper_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_paper;
ex_opts_.push_back(ea);
ea.ind = ex_paper_lateral_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_paper_lateral;
ex_opts_.push_back(ea);
ea.ind = ex_auto_paper_size_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_auto_paper_size;
ex_opts_.push_back(ea);
ea.ind = ex_is_paper_auto_crop_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_auto_paper_crop;
ex_opts_.push_back(ea);
}
void scanner::extension_fill_bkg_method(int id)
{
EXAPI ea;
ea.ind = ex_fill_background_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_fill_background;
ex_opts_.push_back(ea);
}
void scanner::extension_text_direction(int id)
{
EXAPI ea;
ea.ind = ex_text_direction_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_text_direction;
ex_opts_.push_back(ea);
}
void scanner::extension_page(int id)
{
EXAPI ea;
ea.ind = ex_duplex_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_duplex;
ex_opts_.push_back(ea);
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);
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);
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);
}
void scanner::extension_erase_color(int id)
{
EXAPI ea;
ea.ind = ex_color_filter_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_color_filter;
ex_opts_.push_back(ea);
ea.ind = ex_color_enhance_id_ = ex_id_++;
ea.base_ind = id;
ea.ex_api = &scanner::handle_ex_color_enhance;
ex_opts_.push_back(ea);
}
bool scanner::get_option_value_with_parent(int sn, set_opt_value setv, void* param) // return true if handled
{
bool handled = true;
if (sn == scan_count_id_)
{
SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
char* buf = new char[parent->size + 4];
memset(buf, 0, parent->size);
hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, buf);
handled = compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf);
delete[] buf;
if (handled)
{
int count = -1;
value_role role = VAL_ROLE_CURRENT;
buf = (char*)hg_sane_middleware::instance()->get_def_value(handle_, scan_mode_id_);
if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf))
role = value_role(role | VAL_ROLE_DEFAULT);
local_utility::free_memory(buf);
setv(&count, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), param);
}
}
else
handled = false;
return handled;
}
bool scanner::set_option_value_with_parent(int sn, void* data, int* err) // return true if handled
{
bool handled = true;
if (sn == scan_count_id_)
{
SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
char* val = new char[parent->size + 4];
SANE_Int after = 0;
memset(val, 0, parent->size + 4);
hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, val);
if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, val))
{
if (*(int*)data != -1)
{
strcpy(val, OPTION_VALUE_SMZS_SMZDZS);
*err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
}
}
else if (*(int*)data == -1)
{
strcpy(val, OPTION_VALUE_SMZS_LXSM);
*err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
}
handled = false;
}
else
{
handled = false;
}
return handled;
}
int scanner::set_option_value(int sn, SANE_Value_Type type, int size, void* data)
{
char* buf = NULL;
SANE_Bool sb = SANE_FALSE;
SANE_Int si = 0, after = 0;
SANE_Fixed sf = 0;
int ret = SCANNER_ERR_OK;
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_, 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)
{
*(float*)data = 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;
}
scanner::EXAPIPOS scanner::find_ex_api(int op_id)
{
return std::find(ex_opts_.begin(), ex_opts_.end(), op_id);
}
EX_OPTION_HANDLER_IMPL(multiout)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
if (setv)
{
char* cur = new char[desc->size],
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
init = sane_opt_trans::multiout_value_to_twain(def),
val = 0;
local_utility::free_memory(def);
memset(cur, 0, desc->size);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
now = sane_opt_trans::multiout_value_to_twain(cur);
delete[] cur;
{
// parent item ...
SANE_Bool enable = SANE_TRUE;
if (hg_sane_middleware::instance()->get_cur_value(handle_, is_multiout_id_, &enable))
{
if (!enable)
now = MULTI_OUT_NONE;
}
}
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
// we have no 'MULTI_OUT_NONE' item in this option, this is used as is_multiout_id_
val = MULTI_OUT_NONE;
value_role role = val == now ? VAL_ROLE_CURRENT : VAL_ROLE_NONE;
if (!setv(&val, role, data))
break;
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
val = sane_opt_trans::multiout_value_to_twain(desc->constraint.string_list[i]);
if (val == now)
role = VAL_ROLE_CURRENT;
if (val == init)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, data))
break;
}
}
else
set_cur_and_def_value<int>(now, init, setv, data);
} while (0);
}
else
{
char* val = new char[desc->size];
const char* in = sane_opt_trans::multiout_value_from_twain(*(int*)data);
SANE_Int after = 0;
if (in && strcmp(in, "\346\227\240"))
{
// enable multi-out ...
*((SANE_Bool*)val) = SANE_TRUE;
ret = hg_sane_middleware::instance()->set_option(handle_, is_multiout_id_, SANE_ACTION_SET_VALUE, val, &after);
strcpy(val, in);
}
else
{
// disable multi-out, let multiout type side
base_id = is_multiout_id_;
*((SANE_Bool*)val) = SANE_FALSE;
}
if (ret == SANE_STATUS_GOOD)
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
delete[] val;
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(auto_color_type)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
if (setv)
{
len = sane_opt_trans::auto_color_type_to_twain(buf);
setv(&len, VAL_ROLE_CURRENT, data);
}
else
{
SANE_Int after = 0;
strcpy(buf, sane_opt_trans::auto_color_type_from_twain(*(int*)data));
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(color_mode)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
if (setv)
{
char* cur = new char[desc->size],
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
init = sane_opt_trans::color_mode_to_twain(def),
val = 0;
local_utility::free_memory(def);
memset(cur, 0, desc->size);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
now = sane_opt_trans::color_mode_to_twain(cur);
delete[] cur;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
val = sane_opt_trans::color_mode_to_twain(desc->constraint.string_list[i]);
if (val == now)
role = VAL_ROLE_CURRENT;
if (val == init)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, data))
break;
}
}
else
set_cur_and_def_value<int>(now, init, setv, data);
} while (0);
}
else
{
char* val = new char[desc->size];
const char* in = sane_opt_trans::color_mode_from_twain(*(int*)data);
SANE_Int after = 0;
strcpy(val, in);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
delete[] val;
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(sharpen)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
if (setv)
{
char* cur = new char[desc->size],
* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
init = sane_opt_trans::sharpen_to_twain(def),
val = 0;
local_utility::free_memory(def);
memset(cur, 0, desc->size);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
now = sane_opt_trans::sharpen_to_twain(cur);
delete[] cur;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
val = sane_opt_trans::sharpen_to_twain(desc->constraint.string_list[i]);
if (val == now)
role = VAL_ROLE_CURRENT;
if (val == init)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, data))
break;
}
}
else
set_cur_and_def_value<int>(now, init, setv, data);
} while (0);
}
else
{
char* val = new char[desc->size];
const char* in = sane_opt_trans::sharpen_from_twain(*(int*)data);
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
delete[] val;
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(paper)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
int now = sane_opt_trans::paper_to_twain(buf),
init = sane_opt_trans::paper_to_twain(def),
val = 0;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
val = sane_opt_trans::paper_to_twain(desc->constraint.string_list[i]);
if (val == -1)
continue;
if (val == now)
role = VAL_ROLE_CURRENT;
if (val == init)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, data))
break;
}
}
else
set_cur_and_def_value<int>(now, init, setv, data);
} while (0);
}
else if (sane_opt_trans::paper_from_twain(*(int*)data))
{
SANE_Int after = 0;
strcpy(buf, sane_opt_trans::paper_from_twain(*(int*)data));
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
}
else
ret = SCANNER_ERR_INVALID_PARAMETER;
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(paper_lateral)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
const char* lateral_swap = NULL;
bool lateral = false;
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
lateral_swap = sane_opt_trans::switch_paper_lateral(buf);
lateral = sane_opt_trans::is_paper_lateral(buf);
if (setv)
{
setv(&lateral, VAL_ROLE_CURRENT, data);
}
else if (lateral_swap)
{
SANE_Int after = 0;
if (lateral != *(bool*)data)
{
strcpy(buf, lateral_swap);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
}
else
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(auto_paper_size)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
if (setv)
{
bool yes = strcmp(buf, OPTION_VALUE_ZZCC_PPYSCC) == 0;
setv(&yes, VAL_ROLE_CURRENT, data);
}
else
{
SANE_Int after = 0;
strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_PPYSCC : OPTION_VALUE_ZZCC_A4);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(auto_paper_crop)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
if (setv)
{
bool yes = strcmp(buf, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0;
setv(&yes, VAL_ROLE_CURRENT, data);
}
else
{
SANE_Int after = 0;
strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_ZDSMCCZDCQ : OPTION_VALUE_ZZCC_ZDSMCC);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(text_direction)
{
int ret = SCANNER_ERR_OK;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
int len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
float now = .0f, init = sane_opt_trans::text_direction_to_twain(def), val = .0f;
local_utility::free_memory(def);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
now = sane_opt_trans::text_direction_to_twain(buf);
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
val = sane_opt_trans::text_direction_to_twain(desc->constraint.string_list[i]);
if (IS_DOUBLE_EQUAL(val, now))
role = VAL_ROLE_CURRENT;
if (IS_DOUBLE_EQUAL(val, init))
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&val, role, data))
break;
}
}
else
set_cur_and_def_value<float>(now, init, setv, data);
} while (0);
}
else
{
SANE_Int after = 0;
strcpy(buf, sane_opt_trans::text_direction_from_twain(*(float*)data));
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(duplex)
{
int ret = SCANNER_ERR_OK;
bool val = *(bool*)data;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
unsigned len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
void* init = hg_sane_middleware::instance()->get_def_value(handle_, base_id);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
if (val && strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0 ||
!val && strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
setv(&val, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), data);
else if (setv(&val, VAL_ROLE_CURRENT, data))
{
if (strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0)
{
val = true;
setv(&val, VAL_ROLE_DEFAULT, data);
}
if (strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
{
val = false;
setv(&val, VAL_ROLE_DEFAULT, data);
}
}
}
else
{
strcpy(buf, val ? OPTION_VALUE_SMYM_SM : OPTION_VALUE_SMYM_DM);
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(fill_background)
{
int ret = SCANNER_ERR_OK;
bool val = *(bool*)data;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
unsigned len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
set_cur_and_def_value<bool>(strcmp(buf, OPTION_VALUE_BJTCFS_TDBX) == 0, strcmp(init, OPTION_VALUE_BJTCFS_TDBX) == 0, setv, data);
local_utility::free_memory(init);
}
else
{
strcpy(buf, val ? OPTION_VALUE_BJTCFS_TDBX : OPTION_VALUE_BJTCFS_ADBX);
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(discard_blank_page)
{
int ret = SCANNER_ERR_OK;
bool val = *(bool*)data;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
unsigned len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYTY) == 0;
setv(&val, VAL_ROLE_CURRENT, data);
}
else
{
if (val)
strcpy(buf, OPTION_VALUE_SMYM_TGKBYTY);
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(discard_blank_receipt)
{
int ret = SCANNER_ERR_OK;
bool val = *(bool*)data;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
unsigned len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYFPZ) == 0;
setv(&val, VAL_ROLE_CURRENT, data);
}
else
{
if (val)
strcpy(buf, OPTION_VALUE_SMYM_TGKBYFPZ);
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(page_fold)
{
int ret = SCANNER_ERR_OK;
bool val = *(bool*)data;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
unsigned len = desc->size + 4;
char* buf = new char[len];
memset(buf, 0, len);
if (setv)
{
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
val = strcmp(buf, OPTION_VALUE_SMYM_DZ) == 0;
setv(&val, VAL_ROLE_CURRENT, data);
}
else
{
if (val)
strcpy(buf, OPTION_VALUE_SMYM_DZ);
else
{
char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
strcpy(buf, init);
local_utility::free_memory(init);
}
SANE_Int after = 0;
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
return ret;
}
EX_OPTION_HANDLER_IMPL(color_filter) // int (filter_value)
{
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
char* buf = NULL;
unsigned int len = 0;
if (desc)
{
len = desc->size + 4;
buf = new char[len];
memset(buf, 0, len);
if (setv)
{
bool filter = false;
int val = FILTER_NONE, now = FILTER_NONE;
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
if (!filter)
now = val;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
if (!filter && v != FILTER_NONE)
continue;
if (v == now)
role = VAL_ROLE_CURRENT;
if (v == val)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&v, role, data))
break;
}
}
}while (0);
}
else
{
const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), true);
SANE_Int after = 0;
strcpy(buf, val);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
}
return ret;
}
EX_OPTION_HANDLER_IMPL(color_enhance) // int (enhance_value)
{
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
char* buf = NULL;
unsigned int len = 0;
if (desc)
{
len = desc->size + 4;
buf = new char[len];
memset(buf, 0, len);
if (setv)
{
bool filter = false;
int val = ENHANCE_NONE, now = ENHANCE_NONE;
hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
if (filter)
now = val;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
if (filter && v != ENHANCE_NONE)
continue;
if (v == now)
role = VAL_ROLE_CURRENT;
if (v == val)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&v, role, data))
break;
}
}
} while (0);
}
else
{
const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), false);
SANE_Int after = 0;
strcpy(buf, val);
ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
delete[] buf;
}
return ret;
}
EX_OPTION_HANDLER_IMPL(final_compression)
{
int ret = SCANNER_ERR_OK;
int* compression = (int*)data;
unsigned int len = sizeof(*compression);
if (setv)
{
int val = 0;
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_COMPRESSION, &val, &len);
if (ret == SANE_STATUS_GOOD)
{
int i = SANE_COMPRESSION_FIRST;
for (; i < SANE_COMPRESSION_LAST; ++i)
{
value_role role = VAL_ROLE_NONE;
if (i == val)
role = VAL_ROLE_CURRENT;
if (i == SANE_COMPRESSION_NONE)
role = value_role(role | VAL_ROLE_DEFAULT);
int v = sane_opt_trans::compression_to_twain(i);
if (!setv(&v, role, data))
break;
}
}
}
else
{
int val = sane_opt_trans::compression_from_twain(*(int*)data);
len = sizeof(val);
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_COMPRESSION, &val, &len);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(final_format)
{
int ret = SCANNER_ERR_OK;
SANE_FinalImgFormat ff;
unsigned int len = sizeof(ff);
if (setv)
{
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &ff, &len);
if (ret == SANE_STATUS_GOOD)
{
int now = ff.img_format, init = SANE_IMAGE_TYPE_BMP;
std::vector<int> all(sane_opt_trans::support_image_types());
for (int i = 0; i < all.size(); ++i)
{
value_role role = VAL_ROLE_NONE;
ff.img_format = (SANE_ImageType)all[i];
if (ff.img_format == now)
role = VAL_ROLE_CURRENT;
if (ff.img_format == init)
role = value_role(role | VAL_ROLE_DEFAULT);
if (!setv(&ff, role, data))
break;
}
}
}
else
{
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_IMAGE_FORMAT, data, &len);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(serial)
{
int ret = SCANNER_ERR_INVALID_PARAMETER;
if (setv)
{
std::string val("");
ret = control_read_string(IO_CTRL_CODE_GET_SERIAL, val);
if (ret == SANE_STATUS_GOOD)
setv(&val, VAL_ROLE_CURRENT, data);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(to_be_scan)
{
int ret = SCANNER_ERR_OK;
SANE_Bool wait_paper = SANE_FALSE;
unsigned int len = sizeof(wait_paper);
if (setv)
{
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
if (ret == SANE_STATUS_GOOD)
{
bool val = wait_paper == SANE_TRUE;
setv(&val, VAL_ROLE_CURRENT, data);
}
}
else
{
wait_paper = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(scan_with_hole)
{
int ret = SCANNER_ERR_OK;
SANE_Bool with_hole = SANE_FALSE;
unsigned int len = sizeof(with_hole);
if (setv)
{
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WITH_HOLE, &with_hole, &len);
if (ret == SANE_STATUS_GOOD)
{
bool val = with_hole == SANE_TRUE;
setv(&val, VAL_ROLE_CURRENT, data);
}
}
else
{
with_hole = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WITH_HOLE, &with_hole, &len);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(device_code)
{
int ret = SCANNER_ERR_INVALID_PARAMETER;
if (setv)
{
std::string val("");
ret = control_read_string(IO_CTRL_CODE_GET_DEVICE_CODE, val);
if (ret == SANE_STATUS_GOOD)
setv(&val, VAL_ROLE_CURRENT, data);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(power)
{
int ret = SCANNER_ERR_OK;
if (setv)
{
SANE_Power now = SANE_POWER_MINUTES_30, init = SANE_POWER_MINUTES_30;
unsigned int len = sizeof(now);
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_POWER_LEVEL, &now, &len);
for (int i = SANE_POWER_FIRST; i < SANE_POWER_LAST; ++i)
{
value_role role = VAL_ROLE_NONE;
if (i == now)
role = VAL_ROLE_CURRENT;
if (i == init)
role = value_role(role | VAL_ROLE_DEFAULT);
SANE_Power power = (SANE_Power)i;
if (!setv(&power, role, data))
break;
}
}
else
{
SANE_Power power = *((SANE_Power*)data);
unsigned int len = sizeof(power);
ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_POWER_LEVEL, &power, &len);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(hardware_version)
{
int ret = SCANNER_ERR_INVALID_PARAMETER;
if (setv)
{
std::string val("");
ret = control_read_string(IO_CTRL_CODE_GET_HARDWARE_VERSION, val);
if (ret == SANE_STATUS_GOOD)
setv(&val, VAL_ROLE_CURRENT, data);
}
return ret;
}
EX_OPTION_HANDLER_IMPL(ip)
{
int ret = SCANNER_ERR_INVALID_PARAMETER;
if (setv)
{
std::string val("");
ret = control_read_string(IO_CTRL_CODE_GET_IP, val);
if (ret == SANE_STATUS_GOOD)
setv(&val, VAL_ROLE_CURRENT, data);
}
return ret;
}
// ISaneInvoker
COM_API_IMPLEMENT(scanner, int, start(void))
{
2022-06-18 08:48:41 +00:00
int ret = SANE_STATUS_GOOD;
scan_msg_ = "OK";
scan_err_ = false;
hg_sane_middleware::instance()->start(handle_, NULL);
2022-06-15 03:04:40 +00:00
// the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ...
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
ret = hg_sane_middleware::instance()->start(handle_, NULL);
if (ret == SANE_STATUS_GOOD)
{
unsigned int l = sizeof(img_fmt_);
2022-06-29 08:13:05 +00:00
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;
2022-06-29 08:13:05 +00:00
img_fmt_.compress.compression = cmprsn;
2022-06-18 00:54:01 +00:00
working_ = true;
}
2022-06-15 03:04:40 +00:00
prev_start_result_ = ret;
return local_utility::sane_statu_2_scanner_err(ret);
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, int, stop(void))
{
2022-06-18 00:54:01 +00:00
working_ = false;
2022-06-15 03:04:40 +00:00
return hg_sane_middleware::instance()->stop(handle_);
}
COM_API_IMPLEMENT(scanner, void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param))
{
2022-06-18 00:54:01 +00:00
cb_invoker_ = cb;
cb_param_ = param;
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
{
int count = get_scanned_images(milliseconds);
return count > 0;
}
COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
{
2022-06-18 00:54:01 +00:00
size_t count = images_.count();
2022-06-18 08:48:41 +00:00
bool notify = true;
2022-06-15 03:04:40 +00:00
2022-06-18 08:48:41 +00:00
while (count == 0 && milliseconds)
2022-06-15 03:04:40 +00:00
{
2022-06-18 08:48:41 +00:00
MSG msg = { 0 };
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
2022-06-18 00:54:01 +00:00
Sleep(10);
2022-06-18 08:48:41 +00:00
if (!working_)
{
if (notify && indicator_.get())
{
notify = false;
indicator_->notify_scan_over(scan_msg_.c_str(), scan_err_); // Ending by UI
}
else if(ui_quit_)
break;
}
2022-06-18 00:54:01 +00:00
count = images_.count();
if (milliseconds != -1)
2022-06-15 03:04:40 +00:00
{
2022-06-18 00:54:01 +00:00
if (milliseconds <= 10)
2022-06-15 03:04:40 +00:00
break;
2022-06-18 00:54:01 +00:00
milliseconds -= 10;
2022-06-15 03:04:40 +00:00
}
}
return count;
}
2022-06-16 09:28:46 +00:00
COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
2022-06-15 03:04:40 +00:00
{
2022-06-18 00:54:01 +00:00
scanned_img* img = images_.take();
2022-06-15 03:04:40 +00:00
return dynamic_cast<IScanImg*>(img);
}
2022-06-29 08:13:05 +00:00
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header, size_t* bytes))
2022-06-15 03:04:40 +00:00
{
2022-06-29 08:13:05 +00:00
return images_.get_header(header, bytes);
2022-06-15 03:04:40 +00:00
}
COM_API_IMPLEMENT(scanner, bool, is_online(void))
{
return !scanner::get_scanner_name(id_).empty();
}
COM_API_IMPLEMENT(scanner, bool, is_paper_on(void))
{
SANE_Bool on = SANE_FALSE;
unsigned int len = sizeof(on);
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_PAPER_ON, &on, &len) == SANE_STATUS_GOOD)
return on == SANE_TRUE;
else
return false;
}
COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes))
{
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
bool ret = false;
if (desc)
{
if (type)
*type = scanner::from_sane_type(desc->type);
if (limit)
*limit = scanner::from_sane_constraint(desc->constraint_type);
if (bytes)
*bytes = desc->size;
ret = true;
}
return ret;
}
COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* param))
{
EXAPIPOS ex = find_ex_api(sn);
int ret = SANE_STATUS_INVAL;
SANE_Int after = 0;
if (ex == ex_opts_.end())
{
if (get_option_value_with_parent(sn, setval, param))
return true;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
void* init = hg_sane_middleware::instance()->get_def_value(handle_, sn);
ret = SANE_STATUS_GOOD;
if (desc->type == SANE_TYPE_BOOL)
{
SANE_Bool v = SANE_FALSE;
bool val = false;
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &v);
val = v == SANE_TRUE;
set_cur_and_def_value<bool>(val, *(SANE_Bool*)init == SANE_TRUE, setval, param);
}
else if (desc->type == SANE_TYPE_INT)
{
SANE_Int cur = 0, def = *(SANE_Int*)init;
int val = 0;
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
val = cur;
if (sn == resolution_id_)
dpi_ = cur;
2022-06-15 03:04:40 +00:00
do
{
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
{
set_value_range<SANE_Int, int>(cur, def, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setval, param, scanner::to_int);
}
else if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
{
const SANE_Word* v = desc->constraint.word_list;
for (int i = 0; i < v[0]; ++i)
{
value_role role = VAL_ROLE_NONE;
if (v[i + 1] == cur)
role = value_role(role | VAL_ROLE_CURRENT);
if (v[i + 1] == *(SANE_Int*)init)
role = value_role(role | VAL_ROLE_DEFAULT);
val = v[i + 1];
if (!setval(&val, role, param))
break;
}
}
else
set_cur_and_def_value<int>(val, *(SANE_Int*)init, setval, param);
}while (0);
}
else if (desc->type == SANE_TYPE_FIXED)
{
SANE_Fixed cur = 0, def = *(SANE_Fixed*)init;
float val = .0f;
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
if (sn == resolution_id_)
dpi_ = 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);
val = SANE_UNFIX(v[i + 1]);
if (!setval(&val, role, param))
break;
}
}
else
set_cur_and_def_value<float>(val, SANE_UNFIX(*(SANE_Fixed*)init), setval, param);
} while (0);
}
else if (desc->type == SANE_TYPE_STRING)
{
char* buf = new char[desc->size + 4];
std::string val(""), def((char*)init);
memset(buf, 0, desc->size + 4);
hg_sane_middleware::instance()->get_cur_value(handle_, sn, buf);
val = buf;
do
{
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
for (int i = 0; desc->constraint.string_list[i]; ++i)
{
value_role role = VAL_ROLE_NONE;
if (strcmp(desc->constraint.string_list[i], buf) == 0)
role = value_role(role | VAL_ROLE_CURRENT);
if (strcmp(desc->constraint.string_list[i], (char*)init) == 0)
role = value_role(role | VAL_ROLE_DEFAULT);
val = desc->constraint.string_list[i];
if (!setval(&val, role, param))
break;
}
}
else
set_cur_and_def_value<std::string>(val, def, setval, param);
} while (0);
delete[] buf;
}
else
{
ret = SANE_STATUS_INVAL;
}
local_utility::free_memory(init);
}
else
{
ret = (this->*ex->ex_api)(ex->base_ind, param, setval);
}
return ret == SANE_STATUS_GOOD;
}
COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val))
{
EXAPIPOS ex = find_ex_api(sn);
int ret = SANE_STATUS_INVAL;
SANE_Int after = 0;
SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
if (ex == ex_opts_.end())
{
if (!set_option_value_with_parent(sn, val, &ret))
ret = set_option_value(sn, desc->type, desc->size, val);
ret = local_utility::sane_statu_2_scanner_err(ret);
}
else
{
ret = (this->*ex->ex_api)(ex->base_ind, val, NULL);
}
if (sn == resolution_id_)
{
if (desc->type == SANE_TYPE_FIXED)
dpi_ = *(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);
}
2022-06-15 03:04:40 +00:00
// SANE options ID ...
SANE_OPTION_ID_IMPLEMENT(is_multiout)
SANE_OPTION_ID_IMPLEMENT(multiout_type)
SANE_OPTION_ID_IMPLEMENT(color_mode)
SANE_OPTION_ID_IMPLEMENT(erase_color)
SANE_OPTION_ID_IMPLEMENT(erase_multiout_red)
SANE_OPTION_ID_IMPLEMENT(erase_paper_red)
SANE_OPTION_ID_IMPLEMENT(is_erase_background)
SANE_OPTION_ID_IMPLEMENT(background_color_range)
SANE_OPTION_ID_IMPLEMENT(sharpen)
SANE_OPTION_ID_IMPLEMENT(erase_morr)
SANE_OPTION_ID_IMPLEMENT(erase_grids)
SANE_OPTION_ID_IMPLEMENT(error_extend)
SANE_OPTION_ID_IMPLEMENT(is_noise_modify)
SANE_OPTION_ID_IMPLEMENT(noise_threshold)
SANE_OPTION_ID_IMPLEMENT(paper)
SANE_OPTION_ID_IMPLEMENT(is_custom_area)
SANE_OPTION_ID_IMPLEMENT(curstom_area_l)
SANE_OPTION_ID_IMPLEMENT(curstom_area_r)
SANE_OPTION_ID_IMPLEMENT(curstom_area_t)
SANE_OPTION_ID_IMPLEMENT(curstom_area_b)
SANE_OPTION_ID_IMPLEMENT(is_size_check)
SANE_OPTION_ID_IMPLEMENT(page)
SANE_OPTION_ID_IMPLEMENT(blank_page_threshold)
SANE_OPTION_ID_IMPLEMENT(resolution)
SANE_OPTION_ID_IMPLEMENT(image_quality)
SANE_OPTION_ID_IMPLEMENT(is_swap)
SANE_OPTION_ID_IMPLEMENT(is_split)
SANE_OPTION_ID_IMPLEMENT(is_auto_deskew)
SANE_OPTION_ID_IMPLEMENT(is_custom_gamma)
SANE_OPTION_ID_IMPLEMENT(bright)
SANE_OPTION_ID_IMPLEMENT(contrast)
SANE_OPTION_ID_IMPLEMENT(gamma)
SANE_OPTION_ID_IMPLEMENT(is_erase_black_frame)
SANE_OPTION_ID_IMPLEMENT(deep_sample)
SANE_OPTION_ID_IMPLEMENT(threshold)
SANE_OPTION_ID_IMPLEMENT(anti_noise)
SANE_OPTION_ID_IMPLEMENT(margin)
SANE_OPTION_ID_IMPLEMENT(fill_background)
SANE_OPTION_ID_IMPLEMENT(is_anti_permeate)
SANE_OPTION_ID_IMPLEMENT(anti_permeate_level)
SANE_OPTION_ID_IMPLEMENT(is_erase_hole)
SANE_OPTION_ID_IMPLEMENT(search_hole_range)
SANE_OPTION_ID_IMPLEMENT(is_filling_color)
SANE_OPTION_ID_IMPLEMENT(is_ultrasonic_check)
SANE_OPTION_ID_IMPLEMENT(is_check_staple)
SANE_OPTION_ID_IMPLEMENT(scan_mode)
SANE_OPTION_ID_IMPLEMENT(scan_count)
SANE_OPTION_ID_IMPLEMENT(text_direction)
SANE_OPTION_ID_IMPLEMENT(is_rotate_bkg180)
SANE_OPTION_ID_IMPLEMENT(is_check_dogear)
SANE_OPTION_ID_IMPLEMENT(dogear_size)
SANE_OPTION_ID_IMPLEMENT(is_check_skew)
SANE_OPTION_ID_IMPLEMENT(skew_range)
SANE_OPTION_ID_IMPLEMENT(black_white_threshold)
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-06-18 00:54:01 +00:00
// ui ...
COM_API_IMPLEMENT(scanner, bool, ui_show_main(HWND parent))
2022-06-15 03:04:40 +00:00
{
2022-06-18 00:54:01 +00:00
return false;
2022-06-15 03:04:40 +00:00
}
2022-06-18 00:54:01 +00:00
COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan))
2022-06-15 03:04:40 +00:00
{
SANEAPI api = { NULL };
api.sane_cancel_api = inner_sane_cancel;
api.sane_close_api = inner_sane_close;
api.sane_control_option_api = inner_sane_control_option;
api.sane_get_devices_api = inner_sane_get_devices;
api.sane_get_option_descriptor_api = inner_sane_get_option_descriptor;
api.sane_get_parameters_api = inner_sane_get_parameters;
api.sane_get_select_fd_api = inner_sane_get_select_fd;
api.sane_io_control_api = inner_sane_io_control;
api.sane_open_api = inner_sane_open;
api.sane_read_api = inner_sane_read;
api.sane_set_io_mode_api = inner_sane_set_io_mode;
api.sane_start_api = inner_sane_start;
api.sane_strstatus_api = inner_sane_strstatus;
setting_.reset(new dlg_setting(parent, &api, handle_, with_scan, scanner_name_.c_str()));
2022-06-27 01:38:12 +00:00
setting_->set_ui_event_notify(&scanner::ui_callback, this);
if (with_scan)
{
indicator_.reset(new dlg_indicator(parent));
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
}
else
indicator_.reset();
setting_->show();
2022-06-18 08:48:41 +00:00
ui_quit_ = false;
return true;
2022-06-15 03:04:40 +00:00
}
2022-06-18 00:54:01 +00:00
COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent))
2022-06-15 03:04:40 +00:00
{
indicator_.reset(new dlg_indicator(parent));
2022-06-27 01:38:12 +00:00
indicator_->set_ui_event_notify(&scanner::ui_callback, this);
indicator_->show();
2022-06-18 08:48:41 +00:00
ui_quit_ = false;
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();
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
int scanner::handle_event(int ev_code, void* data, unsigned int* len)
2022-06-15 03:04:40 +00:00
{
2022-06-18 00:54:01 +00:00
if (ev_code == SANE_EVENT_IMAGE_OK)
{
SANE_Image* simg = (SANE_Image*)data;
scanned_img* img = NULL;
wchar_t name[40] = { 0 };
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
2022-06-29 08:13:05 +00:00
img = new scanned_img(handle_, simg->header, simg->data, simg->bytes, dpi_, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
if (img->bytes() /*>= simg->bytes*/)
2022-06-18 00:54:01 +00:00
{
images_.save(img);
}
else
{
img->release();
}
2022-06-18 08:48:41 +00:00
if (indicator_)
indicator_->notify_data_arrived(true);
}
else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED)
{
if (indicator_)
indicator_->notify_data_arrived(false);
2022-06-18 00:54:01 +00:00
}
else if (ev_code == SANE_EVENT_SCAN_FINISHED)
{
2022-06-18 08:48:41 +00:00
if (indicator_.get())
{
scan_msg_ = (char*)data;
scan_err_ = *len != SCANNER_ERR_OK;
}
2022-06-18 00:54:01 +00:00
working_ = false;
}
return 0;
2022-06-15 03:04:40 +00:00
}
2022-06-18 00:54:01 +00:00
2022-06-15 03:04:40 +00:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// exports
#ifdef EXPORT_SANE_API
__declspec(dllexport)
#else
__declspec(dllimport)
#endif
int __stdcall initialize(void* reserve)
{
2022-06-18 00:54:01 +00:00
hg_sane_middleware::set_callback(callback::sane_event_callback, NULL);
2022-06-15 03:04:40 +00:00
hg_sane_middleware::instance();
return SANE_STATUS_GOOD;
}
#ifdef EXPORT_SANE_API
__declspec(dllexport)
#else
__declspec(dllimport)
#endif
int __stdcall open_scanner(SCANNERID scanner_id, ISaneInvoker** invoker)
{
if (!invoker)
return SCANNER_ERR_INVALID_PARAMETER;
if (!is_scanner_online(scanner_id))
return SCANNER_ERR_DEVICE_NOT_FOUND;
scanner* scn = new scanner(scanner_id);
*invoker = dynamic_cast<ISaneInvoker*>(scn);
return 0;
}
#ifdef EXPORT_SANE_API
__declspec(dllexport)
#else
__declspec(dllimport)
#endif
bool __stdcall is_scanner_online(SCANNERID scanner_id)
{
return !scanner::get_scanner_name(scanner_id).empty();
}
#ifdef EXPORT_SANE_API
__declspec(dllexport)
#else
__declspec(dllimport)
#endif
int __stdcall uninitialize(void* reserve)
{
2022-06-18 00:54:01 +00:00
hg_sane_middleware::set_callback(NULL, NULL);
2022-06-15 03:04:40 +00:00
hg_sane_middleware::clear();
return 0;
}