增加图像扩展信息接口;增加SANE接口;调整语言包转换方式

This commit is contained in:
gb 2023-01-28 15:19:10 +08:00
parent e3b51facd9
commit 6e968c93f4
10 changed files with 605 additions and 338 deletions

View File

@ -24,6 +24,7 @@ private:
typedef struct _dq
{
size_t bytes;
uint32_t id;
T t;
}DQ;
deque<DQ> _queue;
@ -67,13 +68,13 @@ public:
return isShutDown;
}
void Put(const T task, size_t bytes)
void Put(const T task, size_t bytes, uint32_t id = -1)
{
lock_guard<mutex> lock(_mutex);
if (!isShutDown)
{
{
DQ dq = { bytes, task };
DQ dq = { bytes, id, task };
_queue.push_back(dq);
bytes_ += bytes;
}
@ -82,7 +83,7 @@ public:
}
T Take()
T Take(uint32_t* id = nullptr)
{
unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0)
@ -96,11 +97,13 @@ public:
DQ front(_queue.front());
_queue.pop_front();
bytes_ -= front.bytes;
if (id)
*id = front.id;
return front.t;
}
T Front()
T Front(uint32_t* id = nullptr)
{
unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0)

View File

@ -786,7 +786,7 @@ void final_img_queue::clear(void)
queue_.clear();
}
bool final_img_queue::put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes
, const char* tmp_path, const char* name_leading, const char* ext, int ind)
, const char* tmp_path, const char* name_leading, const char* ext, int ind, uint32_t id)
{
IMGDT imgd;
bool ret = false;
@ -798,6 +798,7 @@ bool final_img_queue::put(int w, int h, int bpp, int channels, int line_bytes, v
imgd.header.height = h;
imgd.header.line_bytes = line_bytes;
imgd.header.width = w;
imgd.header.src_id = id;
imgd.offset = 0;
imgd.data.reset(new tiny_buffer(bytes, tmp_path, name_leading, ext, ind));

View File

@ -214,6 +214,7 @@ typedef struct _img_header
int channels;
int line_bytes;
unsigned bytes;
uint32_t src_id;
}IMH;
typedef struct _img
{
@ -236,7 +237,7 @@ public:
size_t size(void);
void clear(void);
bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes
, const char* tmp_path, const char* name_leading, const char* ext, int ind);
, const char* tmp_path, const char* name_leading, const char* ext, int ind, uint32_t id);
bool front(IMH* header);
void fetch_front(void* buf, int* len, bool* over);
};

View File

@ -156,7 +156,7 @@ hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, usb_io* io,in
, is_kernelsnap_221027_(false), memory_size_(2000/*USB+JPEG压缩及图像处理图队列总共1GB*/), isx86_Advan_(true), stop_fatal_(SCANNER_ERR_OK), is_auto_paper_scan(false)
, size_check(false), save_sleeptime_type_(false), is_kernelsnap_devsislock(false), is_checksum_strat_scan(false), is_cis_image(false)
, is_dpi_color_check(false),save_dpi_color_check_val(0.0f), is_auto_falt(false),HGVersion_mgr_(NULL), HGVersion_Init_(NULL)
, HGVersion_Islock_(NULL), HGVersion_Postlog_(NULL), HGVersion_Free_(NULL), Dynamicopen_HGVersion_pHandle_(NULL),pid_(pid)
, HGVersion_Islock_(NULL), HGVersion_Postlog_(NULL), HGVersion_Free_(NULL), Dynamicopen_HGVersion_pHandle_(NULL),pid_(pid), fetching_id_(-1)
{
#if !defined(_WIN32) && !defined(_WIN64) &&defined(x86_64)
isx86_Advan_ = false;
@ -677,6 +677,13 @@ void hg_scanner::get_range(const char* name, std::vector<std::string>& range, st
else
{
std::string v("");
if (setting_jsn_.at(name).at("range").at(i).is_number())
{
int id = 0;
setting_jsn_.at(name).at("range").at(i).get_to(id);
v = hg_log::lang_load(id);
}
else
setting_jsn_.at(name).at("range").at(i).get_to(v);
range.push_back(v);
}
@ -701,7 +708,9 @@ void hg_scanner::get_range(const char* name, std::vector<std::string>& range, st
def_val = sn;
}
else if (type == "string")
setting_jsn_.at(name).at("default").get_to(def_val);
{
def_val = get_setting_item_string(name, "default");
}
//VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "setting %d has %d range(s) and default value is '%s'\n", setting_no, range.size(), def_val.c_str());
}
bool hg_scanner::check_range(const char* name, bool& val)
@ -848,8 +857,7 @@ int hg_scanner::restore(const char* name)
setting_jsn_.at(name).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(name).at("default").get_to(val);
val = get_setting_item_string(name, "default");
char* buf = NULL;
int size = 0;
@ -913,6 +921,13 @@ bool hg_scanner::get_default_value(void* buf, json* jsn)
else if (type == "string")
{
type = "";
if (jsn->at("default").is_number())
{
int n = 0;
jsn->at("default").get_to(n);
type = hg_log::lang_load(n);
}
else
jsn->at("default").get_to(type);
strcpy((char*)buf, type.c_str());
}
@ -943,7 +958,8 @@ void hg_scanner::thread_handle_image_process(void)
continue;
}
tiny_buffer = imgs_.Take();
uint32_t id = -1;
tiny_buffer = imgs_.Take(&id);
if (tiny_buffer->swap())
{
try
@ -956,7 +972,7 @@ void hg_scanner::thread_handle_image_process(void)
stop();
break;
}
image_process(tiny_buffer);
image_process(tiny_buffer, id);
}
catch (const std::exception& e)
{
@ -968,7 +984,7 @@ void hg_scanner::thread_handle_image_process(void)
else
stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
VLOG_MINI_1(LOG_LEVEL_ALL, "is opencv Fatal: %s\n", e.what());
//stop();
stop();
break;
}
@ -1513,8 +1529,8 @@ int hg_scanner::setting_paper(void* data)
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret));
//if(ret == SCANNER_ERR_NOT_EXACT)
// strcpy((char*)data, paper.c_str());
if(ret == SCANNER_ERR_NOT_EXACT)
strcpy((char*)data, paper.c_str());
if(old != image_prc_param_.bits.paper)
reset_custom_area_range(image_prc_param_.bits.paper);
@ -1566,7 +1582,10 @@ int hg_scanner::setting_resolution(void* data)
resolution_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_RESOLUTION, resolution_))
{
*(int*)data = resolution_;
ret = SCANNER_ERR_NOT_EXACT;
}
// check paper ...
if (!check_paper_and_resolution(resolution_, image_prc_param_.bits.paper))
@ -1874,9 +1893,8 @@ int hg_scanner::setting_scan_mode(void* data)
int hg_scanner::setting_scan_count(void* data)
{
int ret = SCANNER_ERR_OK;
std::string val("");
std::string val(get_setting_item_string(SANE_STD_OPT_NAME_SCAN_MODE, "cur"));
setting_jsn_.at(SANE_STD_OPT_NAME_SCAN_MODE).at("cur").get_to(val);
if (val == hg_log::lang_load(ID_OPTION_VALUE_SMZS_LXSM))
{
scan_count_ = -1;
@ -2366,11 +2384,32 @@ void hg_scanner::init_settings(const char* json_setting_text)
std::string val("");
change_string_2_lang_id(v.c_str(), "title");
change_string_2_lang_id(v.c_str(), "desc");
setting_jsn_.at(v.c_str()).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(v.c_str()).at("default").get_to(val);
change_string_2_lang_id(v.c_str(), "cur");
change_string_2_lang_id(v.c_str(), "default");
if (setting_jsn_.at(v.c_str()).contains("range"))
{
for (int i = 0; i < setting_jsn_.at(v.c_str()).at("range").size(); ++i)
{
int id = -1;
setting_jsn_.at(v.c_str()).at("range").at(i).get_to(val);
id = lang_get_string_id(val.c_str(), true);
if (id == -1)
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str());
}
else
setting_jsn_.at(v.c_str()).at("range")[i] = id;
}
}
val = get_setting_item_string(v.c_str(), "default");
char* buf = NULL;
int size = 0;
@ -2421,6 +2460,40 @@ int hg_scanner::init_settings(int pid)
return SCANNER_ERR_OK;
}
void hg_scanner::change_string_2_lang_id(const char* name, const char* key)
{
std::string val("");
int id = -1;
if (setting_jsn_.at(name).contains(key))
{
setting_jsn_.at(name).at(key).get_to(val);
id = lang_get_string_id(val.c_str(), true);
if (id == -1)
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str());
}
else
setting_jsn_.at(name).at(key) = id;
}
}
std::string hg_scanner::get_setting_item_string(const char* name, const char* key)
{
std::string ret("");
if (setting_jsn_.at(name).at(key).is_number())
{
int n = -1;
setting_jsn_.at(name).at(key).get_to(n);
ret = hg_log::lang_load(n);
}
else
{
setting_jsn_.at(name).at(key).get_to(ret);
}
return std::move(ret);
}
int hg_scanner::on_scann_error(int err)
{
status_ = err;
@ -2636,7 +2709,7 @@ int hg_scanner::save_usb_data(std::shared_ptr<tiny_buffer> data)
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "Warning: memory usage(%.2fMB) maybe leading exception!\r\n", Memoryusae);
}
imgs_.Put(data, data->size());
imgs_.Put(data, data->size(), hg_scanner_mgr::unique_id());
if (wait_img_.is_waiting())
wait_img_.notify();
}
@ -2646,7 +2719,7 @@ int hg_scanner::save_usb_data(std::shared_ptr<tiny_buffer> data)
return ret;
}
int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf, uint32_t id)
{
std::string bw("");
@ -2687,6 +2760,7 @@ int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
img.bytes = head->total_bytes;
img.flag.statu = head->statu;
img.flag.dpi = resolution_;
img.src_id = id;
if (img.flag.statu)
{
@ -2697,7 +2771,7 @@ int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
}
if (final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes
, final_path_.c_str(), "final", "dat", final_img_index_))
, final_path_.c_str(), "final", "dat", final_img_index_, id))
return SCANNER_ERR_OK;
else
return SCANNER_ERR_INSUFFICIENT_MEMORY;
@ -2850,10 +2924,10 @@ int hg_scanner::set_setting(const char* name, void* data, int len)
if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED)
{
std::string type(""), name("");
std::string type(""), name(get_setting_item_string(real_n.c_str(), "title"));
setting_jsn_.at(real_n).at("type").get_to(type);
setting_jsn_.at(real_n).at("title").get_to(name);
// setting_jsn_.at(real_n).at("title").get_to(name);
if (type == "string")
{
setting_jsn_.at(real_n).at("cur") = (char*)data;
@ -2927,18 +3001,18 @@ int hg_scanner::get_setting(const char* name, char* json_txt_buf, int* len, int*
else
{
//json_name.find(real_n)
auto it = json_name.find(real_n);
if (it != json_name.end())
{
int i = it->second;
const char* load = hg_log::lang_load(i);
if (load)
{
setting_jsn_.at(real_n).at("title") = load;
}
}
//auto it = json_name.find(real_n);
//if (it != json_name.end())
//{
// int i = it->second;
//
// const char* load = hg_log::lang_load(i);
// if (*load)
// {
// setting_jsn_.at(real_n).at("title") = load;
// }
//
//}
std::string text(setting_jsn_.at(real_n).dump());
text.insert(0, "\"" + real_n + "\":");
@ -2983,6 +3057,7 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
int ret = SCANNER_ERR_OK;
IMH imh;
fetching_id_ = -1;
bzero(&imh, sizeof(imh));
bzero(ii, sizeof(*ii));
while ((!wait_img_.is_waiting() || !wait_usb_.is_waiting()) && final_imgs_.size() <= 0)
@ -2995,7 +3070,10 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
if (!final_imgs_.front(&imh))
ret = SCANNER_ERR_NO_DATA;
else
{
copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels, imh.bits);
fetching_id_ = imh.src_id;
}
}
if (ret == SCANNER_ERR_NO_DATA /*&& final_img_index_ == 0*/)
@ -3696,7 +3774,7 @@ int hg_scanner::get_scan_is_sleep(SANE_Bool& data)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer)
void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer, uint32_t id)
{
if (!buffer.get() || !ImagePrc_pHandle_)
{
@ -3919,7 +3997,10 @@ void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer)
VLOG_MINI_6(LOG_LEVEL_DEBUG_INFO, "Set img type is:%s Final picture %d (%d * %d * %d) with %u bytes!\n", img_type_.c_str(), index
, ih.width, ih.height, ih.bits * ih.channels, ih.total_bytes);
}
save_final_image(&ih, buf);
if (id == -1)
id = hg_scanner_mgr::unique_id();
save_final_image(&ih, buf, id);
id = -1;
}
}
int hg_scanner::image_configuration(SCANCONF& ic)

View File

@ -146,7 +146,7 @@ class hg_scanner
void working_begin(void*);
void working_done(void*);
void image_process(std::shared_ptr<tiny_buffer>& buff);
void image_process(std::shared_ptr<tiny_buffer>& buffer, uint32_t id);
void reset_custom_area_range(int paper);
float reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u); // return cur value
int set_color_change(void);
@ -362,8 +362,12 @@ protected:
int stop_fatal_;
BlockingQueue<std::shared_ptr<tiny_buffer>> imgs_;
uint32_t fetching_id_; // for sane read image ext info. added on 2023-01-13
void init_settings(const char* json_setting_text);
int init_settings(int pid);
void change_string_2_lang_id(const char* name, const char* key);
std::string get_setting_item_string(const char* name, const char* key);
int on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作
int try_third_app_handle_start(bool& handled);
int try_third_app_after_start(int err);
@ -375,7 +379,7 @@ protected:
void copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels, int bits);
int save_usb_data(std::shared_ptr<tiny_buffer> data);
int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf);
int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf, uint32_t id = -1);
void adjust_filling_hole(LPSCANCONF conf);

View File

@ -92,6 +92,9 @@ std::string hg_scanner_mgr::pe_path_("");
std::string hg_scanner_mgr::pe_name_("");
bool hg_scanner_mgr::read_over_with_eof_ = true;
uint32_t hg_scanner_mgr::unique_img_id_ = 0;;
std::mutex hg_scanner_mgr::mutex_img_id;
hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1)
{
usb_manager::instance()->register_hotplug(&hg_scanner_mgr::usb_event_handle, this);
@ -125,6 +128,7 @@ hg_scanner_mgr* hg_scanner_mgr::instance(sane_callback cb)
hg_scanner_mgr::event_callback_ = cb;
if (cb)
hg_scanner_mgr::async_io_enabled_ = cb(NULL, SANE_EVENT_SUPPORT_ASYNC_IO, NULL, NULL, NULL) == 0;
hg_scanner_mgr::unique_img_id_ = (uint32_t)INT_MAX + 1;
hg_scanner_mgr::inst_ = new hg_scanner_mgr();
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "async image transferring is %s\n", hg_scanner_mgr::async_io_enabled_ ? "enabled" : "disabled");
}
@ -190,6 +194,17 @@ std::string hg_scanner_mgr::get_pe_name(std::string* path)
return hg_scanner_mgr::pe_name_;
}
uint32_t hg_scanner_mgr::unique_id(int type)
{
if (type == UNIQUE_ID_IMG)
{
std::lock_guard<std::mutex> lock(hg_scanner_mgr::mutex_img_id);
return hg_scanner_mgr::unique_img_id_++;
}
return -1;
}
hg_scanner* hg_scanner_mgr::create_scanner_empty(const char* name, usb_io* io, scanner_handle* h)
{

View File

@ -76,6 +76,9 @@ class hg_scanner_mgr
static int ver_build_;
static int ver_patch_;
static uint32_t unique_img_id_;
static std::mutex mutex_img_id;
static hg_scanner_mgr* inst_;
static void usb_event_handle(usb_event ev, libusb_device* device, int vid, int pid, int usb_ver_h, int usb_ver_l, bool* retry, void* user); // usb_ver_h.usb_ver_l
@ -96,6 +99,11 @@ public:
static void set_version(int hh, int hl, int lh, int ll);
static void set_exe_name(const char* path, const char* name);
static std::string get_pe_name(std::string* path = nullptr);
enum
{
UNIQUE_ID_IMG = 0,
};
static uint32_t unique_id(int type = UNIQUE_ID_IMG);
static hg_scanner* create_scanner_empty(const char* name, usb_io* io, scanner_handle* h);
static hg_scanner* create_scanner_g100(const char* name, usb_io* io, scanner_handle* h);

View File

@ -11,8 +11,8 @@ 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 const SANE_Option_Descriptor* inner_sane_get_option_descriptor(SANE_Handle handle, const void* option);
extern SANE_Status inner_sane_control_option(SANE_Handle handle, const void* 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);
@ -24,6 +24,7 @@ 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);
extern SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len);
/// <summary>
/// 导出接口
@ -51,11 +52,11 @@ void sane_close(SANE_Handle handle)
const SANE_Option_Descriptor*
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
{
return inner_sane_get_option_descriptor(handle, option);
return inner_sane_get_option_descriptor(handle, (const void*)option);
}
SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info)
{
return inner_sane_control_option(handle, option, action, value, info);
return inner_sane_control_option(handle, (const void*)option, action, value, info);
}
SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters* params)
{
@ -100,3 +101,16 @@ const char* sane_err_desc(SANE_Status err)
{
return inner_sane_err_desc(err);
}
const SANE_Option_Descriptor*
sane_get_option_descriptor_ex(SANE_Handle handle, const char* option)
{
return inner_sane_get_option_descriptor(handle, (const void*)option);
}
SANE_Status sane_control_option_ex(SANE_Handle handle, const char* option, SANE_Action action, void* value, SANE_Int* info)
{
return inner_sane_control_option(handle, (const void*)option, action, value, info);
}
SANE_Status sane_read_ext_info(SANE_Img_Ext_Info* ext_info, SANE_Int* len)
{
return inner_sane_read_ext(ext_info, len);
}

View File

@ -339,7 +339,7 @@ namespace local_utility
hg_sane_middleware* hg_sane_middleware::inst_ = NULL;
const SANE_Device** hg_sane_middleware::dev_list_ = NULL;
hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), std_opt_(nullptr), init_ok_(false)
hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false)
{
if (lang_initialize() == -1)
{
@ -369,17 +369,14 @@ hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), std_opt_(nullptr
hg_sane_middleware::~hg_sane_middleware()
{
register_language_changed_notify(&hg_sane_middleware::language_changed, false);
for (size_t i = 0; i < opts_.size(); ++i)
{
local_utility::free_memory(opts_[i].desc);
}
for (size_t i = 0; i < openning_.size(); ++i)
hg_scanner_close(openning_[i].handle, true);
{
hg_scanner_close(openning_[i]->dev, true);
hg_sane_middleware::free_device_inst(openning_[i]);
}
hg_scanner_uninitialize();
if (opt_0_)
local_utility::free_memory(opt_0_);
if (std_opt_)
delete std_opt_;
}
void hg_sane_middleware::language_changed(int cp, void* param)
@ -453,6 +450,18 @@ double hg_sane_middleware::sane_fixed_2_double(SANE_Fixed v)
{
return SANE_UNFIX(v);
}
void hg_sane_middleware::set_value_to_var(void* val, size_t bytes, void* param)
{
memcpy(param, val, bytes);
}
void hg_sane_middleware::set_value_to_new(void* val, size_t bytes, void* param)
{
void** addr = (void**)param;
*addr = local_utility::acquire_memory(bytes, "set_value_to_new");
memcpy(*addr, val, bytes);
}
std::string hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void* val)
{
std::string ret("unknown");
@ -486,35 +495,13 @@ std::string hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void
return ret;
}
std::string hg_sane_middleware::sane_path(void)
{
return g_sane_path;
}
hg_sane_middleware* hg_sane_middleware::instance(void)
{
if (!hg_sane_middleware::inst_)
hg_sane_middleware::inst_ = new hg_sane_middleware();
return hg_sane_middleware::inst_;
}
void hg_sane_middleware::set_callback(sane_callback cb, void* param)
{
local_utility::set_callback(cb, param);
}
void hg_sane_middleware::clear(void)
{
local_utility::stop_work();
if (hg_sane_middleware::inst_)
{
delete hg_sane_middleware::inst_;
hg_sane_middleware::inst_ = NULL;
}
}
scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h)
{
if (!h)
return nullptr;
int bits = sizeof(h) / 2 * 8;
unsigned long long v = (unsigned long long)h;
uint64_t v = (uint64_t)h;
v ^= v >> bits;
@ -522,8 +509,11 @@ scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h)
}
SANE_Handle hg_sane_middleware::scanner_handle_to_sane(scanner_handle h)
{
if (!h)
return nullptr;
int bits = sizeof(h) / 2 * 8;
unsigned long long v = (unsigned long long)h;
uint64_t v = (uint64_t)h;
v ^= v >> bits;
@ -753,30 +743,46 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
return sod;
}
std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key)
{
std::string str("");
int id = -1;
void hg_sane_middleware::on_device_closed(scanner_handle h)
if (jsn->get_value(key, id) && id != -1)
{
// 由于ç®å‰<C3A5>对多设备的支æŒ<C3A6>还ä¸<C3A4>是刚需,故代ç <C3A7>å<EFBFBD>ªè€ƒè™å<E28098>•è®¾å¤‡æƒ…况,设备关闭å<C2AD>Žï¼Œæ¸…除所有å<E280B0>˜é‡?
for (size_t i = 0; i < opts_.size(); ++i)
{
local_utility::free_memory(opts_[i].desc);
str = lang_load_string(id, &id);
}
opts_.clear();
for (size_t i = 0; i < openning_.size(); ++i)
else
jsn->get_value(key, str);
return std::move(str);
}
std::string hg_sane_middleware::sane_path(void)
{
if (openning_[i].handle == h)
return g_sane_path;
}
hg_sane_middleware* hg_sane_middleware::instance(void)
{
openning_.erase(openning_.begin() + i);
i--;
if (!hg_sane_middleware::inst_)
hg_sane_middleware::inst_ = new hg_sane_middleware();
return hg_sane_middleware::inst_;
}
void hg_sane_middleware::set_callback(sane_callback cb, void* param)
{
local_utility::set_callback(cb, param);
}
void hg_sane_middleware::clear(void)
{
local_utility::stop_work();
if (hg_sane_middleware::inst_)
{
delete hg_sane_middleware::inst_;
hg_sane_middleware::inst_ = NULL;
}
}
cur_vals_.clear();
slave_options_.clear();
master_options_.clear();
if (std_opt_)
delete std_opt_;
std_opt_ = nullptr;
}
SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc)
{
scanner_handle h = NULL;
@ -788,19 +794,18 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle*
err = hg_scanner_open(&h, devicename, false, NULL, NULL, NULL, rsc);
if (err == SCANNER_ERR_OK)
{
OPENDEV od;
LPDEVINST inst = new DEVINST;
od.dev_name = devicename;
od.handle = h;
od.scan_count = -1;
openning_.push_back(od);
inst->name = devicename;
inst->dev = h;
openning_.push_back(inst);
*handle = hg_sane_middleware::scanner_handle_to_sane(h);
if (!local_utility::cb_ui_)
{
long count = 0;
hg_scanner_get_parameter(h, 0, NULL, &count);
std_opt_ = new sane_std_opts(count);
inst->std_opt = new sane_std_opts(count);
}
return SANE_STATUS_GOOD;
@ -812,16 +817,15 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle*
else
return (SANE_Status)err; // SANE_STATUS_UNSUPPORTED;
}
SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, json* jsn, int opt_no)
SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, json* jsn)
{
std::string title(""), desc(""), val("");
std::string title(hg_sane_middleware::get_string_in_json(jsn, "title")),
desc(hg_sane_middleware::get_string_in_json(jsn, "desc")),
val("");
std::vector<std::string> constraints;
double lower = .0f, upper = .0f, step = .0f;
bool db_val = false;
jsn->get_value("title", title);
jsn->get_value("desc", desc);
if (!jsn->get_value("type", val))
return NULL;
@ -836,9 +840,41 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
{
if (range->first_child(val))
{
size_t pos = val.find(".");
if (pos != std::string::npos)
{
for (size_t i = val.length() - 1; i > pos; --i)
{
if (val[i] != '0')
{
pos = i + 1;
break;
}
}
val.erase(pos);
}
if (std::to_string(atoi(val.c_str())) == val)
constraints.push_back(lang_load_string(atoi(val.c_str()), (int*)&lower));
else
constraints.push_back(val);
while (range->next_child(val))
{
pos = val.find(".");
if (pos != std::string::npos)
{
for (size_t i = val.length() - 1; i > pos; --i)
{
if (val[i] != '0')
{
pos = i + 1;
break;
}
}
val.erase(pos);
}
if (std::to_string(atoi(val.c_str())) == val)
constraints.push_back(lang_load_string(atoi(val.c_str()), (int*)&lower));
else
constraints.push_back(val);
}
}
@ -866,6 +902,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
lower = l;
upper = u;
step = s;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s range: [%d, +%d, %d]\n", name.c_str(), l, s, u);
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, false, &lower, &upper, &step);
}
@ -891,6 +928,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
range->get_value("max", upper);
step = (upper - lower) / 10.0f;
range->get_value("step", step);
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s range: (%f, +%f, %f)\n", name.c_str(), lower, step, upper);
ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, true, &lower, &upper, &step);
}
@ -977,7 +1015,8 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
}
if (depend)
{
if (parse_depends(depend, so))
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(h);
if (it != openning_.end() && parse_depends(depend, so, (*it)->masters))
{
so.enable_now = (ret->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE;
so.name = name;
@ -996,13 +1035,13 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
integer = master == "int";
master = "";
m->get_value_as_string("cur", master, integer);
so.enable_now = so.is_enable(so.master, cur_vals_);
so.enable_now = so.is_enable(so.master, (*it)->cur_vals);
if (!so.enable_now)
ret->cap |= SANE_CAP_INACTIVE;
}
delete m;
}
slave_options_.push_back(so);
(*it)->slaves.push_back(so);
}
delete depend;
}
@ -1010,10 +1049,19 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
return ret;
}
scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv, OPENDEV* dev)
void hg_sane_middleware::free_device_inst(LPDEVINST dev)
{
if (dev->std_opt)
delete dev->std_opt;
for (auto& v : dev->opts)
local_utility::free_memory(v.desc);
delete dev;
}
scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv, LPDEVINST* dev)
{
scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h);
std::vector<OPENDEV>::iterator it = std::find(openning_.begin(), openning_.end(), handle);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (it == openning_.end())
handle = NULL;
@ -1022,12 +1070,16 @@ scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv,
if (dev)
*dev = *it;
if (rmv)
{
if (!dev)
hg_sane_middleware::free_device_inst(*it);
openning_.erase(it);
}
}
return handle;
}
std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt, std::string* key)
std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt, std::string* key, SANE_Int* id)
{
char* json_txt = NULL;
long length = 0;
@ -1038,7 +1090,7 @@ std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt
{
json_txt = (char*)local_utility::acquire_memory(ALIGN_INT(length + 4), "hg_sane_middleware::get_option_json");
bzero(json_txt, length + 4);
err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length);
err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length, id);
if (err == SCANNER_ERR_OK)
{
const char* head = json_txt;
@ -1068,42 +1120,43 @@ std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt
return ret;
}
SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(const char* name, unsigned long long option)
SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id)
{
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (it != openning_.end())
{
if (IS_PTR_NUMBER(option))
{
for (const auto& v : opts_)
if (id)
*id = (int)option;
for (const auto& v : (*it)->opts)
{
if (v.dev_name == name && v.option_no == option)
if (v.option_no == (int)option)
return v.desc;
}
}
else
{
for (const auto& v : opts_)
for (const auto& v : (*it)->opts)
{
if (v.dev_name == name && v.opt_name == (const char*)option)
if (v.opt_name == (const char*)option)
{
if (id)
*id = v.option_no;
return v.desc;
}
}
return NULL;
}
SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(SANE_Handle handle, unsigned long long option)
{
OPENDEV dev;
scanner_handle h = find_openning_device(handle, false, &dev);
}
if (!h)
return NULL;
else
return find_stored_descriptor(dev.dev_name.c_str(), option);
}
void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector<std::string>* changed)
{
long count = 0;
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (changed)
changed->clear();
@ -1116,13 +1169,13 @@ void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector
if (jsn->attach_text(&val[0]) &&
jsn->get_value("type", val))
{
if (refresh_current_value(key.c_str(), jsn))
if (refresh_current_value(*it, key.c_str(), jsn))
changed->push_back(key);
}
delete jsn;
}
}
bool hg_sane_middleware::get_current_value(scanner_handle handle, int option, void* value, SANE_Value_Type* type)
bool hg_sane_middleware::get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type)
{
std::string name(""),
val(get_option_json(handle, (void *)option, &name));
@ -1140,37 +1193,50 @@ bool hg_sane_middleware::get_current_value(scanner_handle handle, int option, vo
{
int v = 0;
jsn->get_value("cur", v);
*((SANE_Int*)value) = v;
// *((SANE_Int*)value) = v;
setv(&v, sizeof(v), value);
t = SANE_TYPE_INT;
}
else if (val == "bool")
{
bool yesorno = false;
jsn->get_value("cur", yesorno);
*(SANE_Bool*)value = yesorno;
bool bv = false;
SANE_Bool v = SANE_FALSE;
jsn->get_value("cur", bv);
// *(SANE_Bool*)value = v;
v = bv;
setv(&v, sizeof(v), value);
t = SANE_TYPE_BOOL;
}
else if (val == "float")
{
double v = .0f;
jsn->get_value("cur", v);
*((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(v);
double dv = .0f;
SANE_Fixed v = 0;
jsn->get_value("cur", dv);
v = hg_sane_middleware::double_2_sane_fixed(dv);
setv(&v, sizeof(v), value);
t = SANE_TYPE_FIXED;
}
else
{
val = "";
jsn->get_value("cur", val);
strcpy((char*)value, val.c_str());
int size = 0;
jsn->get_value("size", size);
val = hg_sane_middleware::get_string_in_json(jsn, "cur");
if (size <= val.length())
size = val.length() + 1;
//strcpy((char*)value, val.c_str());
setv(&val[0], size, value);
estimate += val.length();
}
if (type)
*type = t;
refresh_current_value(name.c_str(), jsn);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
refresh_current_value(*it, name.c_str(), jsn);
jsn->get_value("title", val);
if (setv == &hg_sane_middleware::set_value_to_new)
value = *(void**)value;
VLOG_MINI_3(LOG_LEVEL_ALL, "<--Get option(%d - %s) value: %s\n", option, val.c_str(), hg_sane_middleware::option_value_2_string(t, value).c_str());
}
@ -1178,7 +1244,7 @@ bool hg_sane_middleware::get_current_value(scanner_handle handle, int option, vo
return ret;
}
void* hg_sane_middleware::get_default_value(scanner_handle handle, int option, int* bytes, bool log)
void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* option, int* bytes, bool log)
{
std::string val(get_option_json(handle, (void *)option));
void* data = nullptr;
@ -1238,8 +1304,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, int option, i
int size = 0;
jsn->get_value("size", size);
val = "";
jsn->get_value("default", val);
val = hg_sane_middleware::get_string_in_json(jsn, "default");
if (size < (int)val.length())
size = val.length();
@ -1259,9 +1324,15 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, int option, i
}
delete jsn;
if (!data && std_opt_)
if (!data)
{
data = std_opt_->get_default_value(handle, option);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (it != openning_.end() && (*it)->std_opt)
{
SANE_Int id = -1;
find_stored_descriptor(handle, option, &id);
data = (*it)->std_opt->get_default_value(handle, id);
}
}
return data;
@ -1332,8 +1403,6 @@ SANE_Status hg_sane_middleware::close_device(SANE_Handle h)
if (hs)
err = local_utility::scanner_err_2_sane_statu(hg_scanner_close(hs, true));
if (err == SANE_STATUS_GOOD)
on_device_closed(hs);
return err;
}
@ -1351,12 +1420,12 @@ SANE_Status hg_sane_middleware::get_image_parameters(SANE_Handle handle, SANE_Pa
}
SANE_Status hg_sane_middleware::start(SANE_Handle h, void* async_event)
{
OPENDEV dev;
scanner_handle hs = find_openning_device(h, false, &dev);
LPDEVINST dev;
scanner_handle hs = find_openning_device(h);
scanner_err err = SCANNER_ERR_INVALID_PARAMETER;
if(hs)
err = hg_scanner_start(hs, async_event, dev.scan_count);
err = hg_scanner_start(hs, async_event, -1);
return local_utility::scanner_err_2_sane_statu(err);
}
@ -1383,16 +1452,16 @@ SANE_Status hg_sane_middleware::stop(SANE_Handle h)
return SANE_STATUS_GOOD;
}
SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, SANE_Int option)
SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, const void* option)
{
OPENDEV dev;
scanner_handle handle = find_openning_device(h, false, &dev);
SANE_Option_Descriptor* ret = NULL;
SANE_Option_Descriptor* ret = nullptr;
scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h);
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
SANE_Int id = -1;
if (!handle)
return NULL;
if (option == 0)
if (!handle || it == openning_.end())
return nullptr;
else if (option == 0)
{
if (!opt_0_)
{
@ -1408,29 +1477,28 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h,
return opt_0_;
}
ret = find_stored_descriptor(dev.dev_name.c_str(),option);
ret = find_stored_descriptor(handle, option, &id);
if (!ret)
{
std::string key(""),
json_txt(get_option_json(handle, (SANE_Int*)option, &key));
json_txt(get_option_json(handle, (void*)option, &key, &id));
if (json_txt.length())
{
json* jsn = new json();
if (jsn->attach_text(&json_txt[0]))
{
ret = from_json(handle, key, jsn, option);
ret = from_json(handle, key, jsn);
if (ret)
{
DEVOPT devopt;
devopt.dev_name = dev.dev_name;
devopt.option_no = option;
devopt.option_no = id;
devopt.desc = ret;
devopt.opt_name = key;
opts_.push_back(devopt);
devopt.opt_name = std::move(key);
(*it)->opts.push_back(std::move(devopt));
refresh_current_value(devopt.opt_name.c_str(), jsn);
refresh_current_value(*it, ret->name, jsn);
}
}
delete jsn;
@ -1439,17 +1507,17 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h,
if (ret)
{
if (std_opt_)
std_opt_->init_known_opt(option, ret);
if ((*it)->std_opt)
(*it)->std_opt->init_known_opt(id, ret);
}
else if (std_opt_)
ret = std_opt_->get_option(option);
else if ((*it)->std_opt)
ret = (*it)->std_opt->get_option(id);
return ret;
}
SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_Action action, void* value, SANE_Int* after_do)
SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do)
{
OPENDEV dev;
LPDEVINST dev = nullptr;
scanner_handle handle = find_openning_device(h, false, &dev);
if (!handle || (action == SANE_ACTION_GET_VALUE && !value))
@ -1472,12 +1540,14 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
}
else
{
if (std_opt_ && std_opt_->is_known_option(option))
SANE_Int id = -1;
find_stored_descriptor(handle, option, &id);
if (dev->std_opt && dev->std_opt->is_known_option(id))
{
std_opt_->get_value(h, option, value);
dev->std_opt->get_value(h, id, value);
ret = SANE_STATUS_GOOD;
}
else if(get_current_value(handle, option, value))
else if(get_current_value(handle, option, &hg_sane_middleware::set_value_to_var, value))
ret = SANE_STATUS_GOOD;
}
@ -1485,19 +1555,20 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
}
else
{
SANE_Option_Descriptor* desc = find_stored_descriptor(dev.dev_name.c_str(), option);
SANE_Int id = -1;
SANE_Option_Descriptor* desc = find_stored_descriptor(handle, option, &id);
bool release_value = false;
scanner_err err = SCANNER_ERR_OK;
SANE_Status status = SANE_STATUS_GOOD;
std::string prev(""), v("");
if (std_opt_ && std_opt_->is_known_option(option, &desc))
if (dev->std_opt && dev->std_opt->is_known_option(id, &desc))
{
SANE_Option_Descriptor* known = std_opt_->get_option(option);
SANE_Option_Descriptor* known = dev->std_opt->get_option(id);
unsigned char* cont = (unsigned char*)value;
prev = hg_sane_middleware::option_value_2_string(known->type, value);
VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "$First 4-bytes of origin value for option %d is: %02X%02X%02X%02X\n", option, cont[0], cont[1], cont[2], cont[3]);
err = std_opt_->set_value(handle, option, value);
err = dev->std_opt->set_value(handle, id, value);
v = hg_sane_middleware::option_value_2_string(known->type, value);
}
else
@ -1569,16 +1640,16 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
if (err == SCANNER_ERR_OK)
{
err = (scanner_err)something_after_do(handle, dev.dev_name.c_str(), desc->name, v.c_str());
err = (scanner_err)something_after_do(dev, desc->name, v.c_str());
}
else if (err == SCANNER_ERR_NOT_EXACT)
{
err = (scanner_err)(something_after_do(handle, dev.dev_name.c_str(), desc->name, v.c_str()) | SANE_INFO_INEXACT);
err = (scanner_err)(something_after_do(dev, desc->name, v.c_str()) | SANE_INFO_INEXACT);
}
else if (err == SCANNER_ERR_CONFIGURATION_CHANGED)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects other options value, RELOAD ...\n", desc->title);
on_SCANNER_ERR_CONFIGURATION_CHANGED(handle, dev.dev_name.c_str());
on_SCANNER_ERR_CONFIGURATION_CHANGED(dev);
err = (scanner_err)SANE_INFO_RELOAD_OPTIONS;
}
else if (err == SCANNER_ERR_ACCESS_DENIED)
@ -1600,16 +1671,28 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
return status;
}
}
bool hg_sane_middleware::get_cur_value(SANE_Handle handle, int option, void* value, SANE_Value_Type* type)
bool hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type)
{
scanner_handle h = find_openning_device(handle);
if (!h)
return false;
return get_current_value(h, option, value, type);
return get_current_value(h, option, &hg_sane_middleware::set_value_to_var, value, type);
}
void* hg_sane_middleware::get_def_value(SANE_Handle handle, int option, int* bytes, bool log)
void* hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, SANE_Value_Type* type)
{
scanner_handle h = find_openning_device(handle);
void* buf = nullptr;
if (!h)
return NULL;
get_current_value(h, option, &hg_sane_middleware::set_value_to_new, &buf, type);
return buf;
}
void* hg_sane_middleware::get_def_value(SANE_Handle handle, void* option, int* bytes, bool log)
{
scanner_handle h = find_openning_device(handle);
@ -1620,8 +1703,8 @@ void* hg_sane_middleware::get_def_value(SANE_Handle handle, int option, int* byt
}
SANE_Status hg_sane_middleware::io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len)
{
OPENDEV od;
scanner_handle handle = find_openning_device(h, false, &od);
LPDEVINST dev;
scanner_handle handle = find_openning_device(h, false, &dev);
int ret = SANE_STATUS_GOOD;
// commented at 2022-03-23 for getting app about info before open any device
@ -1633,7 +1716,7 @@ SANE_Status hg_sane_middleware::io_control(SANE_Handle h, unsigned long code, vo
{
int nc = code;
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc);
on_SCANNER_ERR_CONFIGURATION_CHANGED(handle, od.dev_name.c_str());
on_SCANNER_ERR_CONFIGURATION_CHANGED(dev);
}
return local_utility::scanner_err_2_sane_statu(ret);
@ -1813,7 +1896,7 @@ bool hg_sane_middleware::parse_master_option(const char* depend_str, MASTEROP& m
return ret;
}
bool hg_sane_middleware::parse_depends(json* jsn, SLAVEOP& so)
bool hg_sane_middleware::parse_depends(json* jsn, SLAVEOP& so, std::vector<std::string>& master)
{
std::string val(""), mn("");
bool ret = jsn->first_child(val);
@ -1831,10 +1914,10 @@ bool hg_sane_middleware::parse_depends(json* jsn, SLAVEOP& so)
else
mn = mo.name;
so.master.push_back(mo);
if (std::find(master_options_.begin(), master_options_.end(), mo.name) == master_options_.end())
if (std::find(master.begin(), master.end(), mo.name) == master.end())
{
master_options_.push_back(mo.name);
std::sort(master_options_.begin(), master_options_.end());
master.push_back(mo.name);
std::sort(master.begin(), master.end());
}
ret = jsn->next_child(val);
}
@ -1857,9 +1940,9 @@ bool hg_sane_middleware::is_associatived(const SLAVEOP& slave, const char* maste
return result;
}
bool hg_sane_middleware::set_stored_option_enabled(const char* dev_name, unsigned long long option, bool enable, int* size)
bool hg_sane_middleware::set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size)
{
SANE_Option_Descriptor* opt = find_stored_descriptor(dev_name, option);
SANE_Option_Descriptor* opt = find_stored_descriptor(h, option);
bool ret = false;
if (opt)
@ -1875,14 +1958,14 @@ bool hg_sane_middleware::set_stored_option_enabled(const char* dev_name, unsigne
return ret;
}
int hg_sane_middleware::something_after_do(scanner_handle h, const char* dev_name, const char* master_name, const char* cur_val)
int hg_sane_middleware::something_after_do(LPDEVINST dev, const char* master_name, const char* cur_val)
{
int after = 0;
OPTENABLE oe;
std::vector<OPTENABLE> changed_options;
refresh_current_value(master_name, cur_val);
if (std::find(master_options_.begin(), master_options_.end(), master_name) == master_options_.end())
refresh_current_value(dev, master_name, cur_val);
if (std::find(dev->masters.begin(), dev->masters.end(), master_name) == dev->masters.end())
{
return after;
}
@ -1892,32 +1975,32 @@ int hg_sane_middleware::something_after_do(scanner_handle h, const char* dev_nam
changed_options.push_back(oe);
for (size_t i = 0; i < changed_options.size(); ++i)
{
for (size_t slave = 0; slave < slave_options_.size(); ++slave)
for (size_t slave = 0; slave < dev->slaves.size(); ++slave)
{
if (slave_options_[slave].name == changed_options[i].name ||
!is_associatived(slave_options_[slave], changed_options[i].name.c_str()))
if (dev->slaves[slave].name == changed_options[i].name ||
!is_associatived(dev->slaves[slave], changed_options[i].name.c_str()))
continue;
bool enable = changed_options[i].enable;
int bytes = 0;
// if (enable)
enable = slave_options_[slave].is_enable(slave_options_[slave].master, cur_vals_);
if (enable == slave_options_[slave].enable_now)
enable = dev->slaves[slave].is_enable(dev->slaves[slave].master, dev->cur_vals);
if (enable == dev->slaves[slave].enable_now)
continue;
slave_options_[slave].enable_now = enable;
if (!set_stored_option_enabled(dev_name, (unsigned long long )slave_options_[slave].name.c_str(), enable, &bytes))
dev->slaves[slave].enable_now = enable;
if (!set_stored_option_enabled(dev->dev, dev->slaves[slave].name.c_str(), enable, &bytes))
continue;
OPTEN* op = get_control_enalbe_data(slave_options_[slave]);
hg_scanner_control(h, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL);
OPTEN* op = get_control_enalbe_data(dev, dev->slaves[slave]);
hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL);
free_control_enable_data(op);
if (std::find(changed_options.begin(), changed_options.end(), slave_options_[slave].name) != changed_options.end())
if (std::find(changed_options.begin(), changed_options.end(), dev->slaves[slave].name) != changed_options.end())
continue;
oe.name = slave_options_[slave].name;
oe.enable = slave_options_[slave].enable_now;
oe.name = dev->slaves[slave].name;
oe.enable = dev->slaves[slave].enable_now;
changed_options.push_back(oe);
}
}
@ -1927,16 +2010,16 @@ int hg_sane_middleware::something_after_do(scanner_handle h, const char* dev_nam
return after;
}
bool hg_sane_middleware::refresh_current_value(const char* name, json* jsn)
bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, json* jsn)
{
std::vector<CURVAL>::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), name);
if (it == cur_vals_.end())
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it == dev->cur_vals.end())
{
CURVAL cv;
jsn->get_value("type", cv.type);
cv.name = name;
jsn->get_value_as_string("cur", cv.val, cv.type == "int");
cur_vals_.push_back(cv);
dev->cur_vals.push_back(cv);
return false;
}
@ -1948,10 +2031,10 @@ bool hg_sane_middleware::refresh_current_value(const char* name, json* jsn)
return old != it->val;
}
}
bool hg_sane_middleware::refresh_current_value(const char* name, const char* val)
bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, const char* val)
{
std::vector<CURVAL>::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), name);
if (it != cur_vals_.end())
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it != dev->cur_vals.end())
{
bool ret = strcmp(it->val.c_str(), val) == 0;
@ -1962,7 +2045,7 @@ bool hg_sane_middleware::refresh_current_value(const char* name, const char* val
return false;
}
OPTEN* hg_sane_middleware::get_control_enalbe_data(const SLAVEOP& slave)
OPTEN* hg_sane_middleware::get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave)
{
std::vector<std::string> master;
OPTEN* opt = NULL;
@ -1982,8 +2065,8 @@ OPTEN* hg_sane_middleware::get_control_enalbe_data(const SLAVEOP& slave)
opt->master_count = 0;
for (size_t i = 0; i < master.size(); ++i)
{
std::vector<CURVAL>::iterator m = std::find(cur_vals_.begin(), cur_vals_.end(), master[i]);
if (m == cur_vals_.end())
std::vector<CURVAL>::iterator m = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), master[i]);
if (m == dev->cur_vals.end())
continue;
opt->master[opt->master_count].name = master[i];
@ -2020,20 +2103,40 @@ void hg_sane_middleware::free_control_enable_data(OPTEN* opt)
free(opt);
}
}
void hg_sane_middleware::on_SCANNER_ERR_CONFIGURATION_CHANGED(scanner_handle handle, const char* dev_name)
void hg_sane_middleware::on_SCANNER_ERR_CONFIGURATION_CHANGED(LPDEVINST dev)
{
std::vector<std::string> changed;
reload_current_value(handle, &changed);
reload_current_value(dev->dev, &changed);
if (changed.size())
{
for (size_t i = 0; i < changed.size(); ++i)
{
std::vector<CURVAL>::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), changed[i]);
if (it != cur_vals_.end())
something_after_do(handle, dev_name, it->name.c_str(), it->val.c_str());
std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), changed[i]);
if (it != dev->cur_vals.end())
something_after_do(dev, it->name.c_str(), it->val.c_str());
}
}
}
std::vector<LPDEVINST>::iterator hg_sane_middleware::find_openning_device_in_que(scanner_handle h)
{
for (size_t i = 0; i < openning_.size(); ++i)
{
if (openning_[i]->dev == h)
return openning_.begin() + i;
}
return openning_.end();
}
std::vector<LPDEVINST>::iterator hg_sane_middleware::find_openning_device_in_que(const char* name)
{
for (size_t i = 0; i < openning_.size(); ++i)
{
if (openning_[i]->name == name)
return openning_.begin() + i;
}
return openning_.end();
}
/// </summary>
/// <summary>
@ -2069,11 +2172,11 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
hg_sane_middleware::instance()->close_device(handle);
}
const SANE_Option_Descriptor*
inner_sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
inner_sane_get_option_descriptor(SANE_Handle handle, const void* option)
{
return hg_sane_middleware::instance()->get_option_descriptor(handle, option);
}
SANE_Status inner_sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info)
SANE_Status inner_sane_control_option(SANE_Handle handle, const void* option, SANE_Action action, void* value, SANE_Int* info)
{
return hg_sane_middleware::instance()->set_option(handle, option, action, value, info);
}
@ -2135,6 +2238,10 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
{
return hg_scanner_err_description(local_utility::sane_statu_2_scanner_err(err));
}
SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len)
{
return SANE_STATUS_UNSUPPORTED;
}
void sanei_debug_msg(int level, int max_level, const char* be, const char* fmt, va_list ap)
{

View File

@ -26,70 +26,13 @@
class json;
class sane_std_opts;
class hg_sane_middleware
{
typedef struct _device_option
{
std::string dev_name;
// std::string dev_name;
int option_no;
std::string opt_name;
SANE_Option_Descriptor* desc;
}DEVOPT;
std::vector<DEVOPT> opts_;
SANE_Option_Descriptor* opt_0_;
sane_std_opts* std_opt_;
bool init_ok_;
typedef struct _openning_scanner_option
{
std::string dev_name;
scanner_handle handle;
int scan_count;
//struct _openning_scanner_option()
//{
// dev_name = "";
// handle = NULL;
// option_no = 0;
// desc = NULL;
//}
bool operator==(const char* name)
{
return strcmp(dev_name.c_str(), name) == 0;
}
bool operator==(scanner_handle h)
{
return handle == h;
}
}OPENDEV;
std::vector<OPENDEV> openning_;
static hg_sane_middleware *inst_;
static const SANE_Device** dev_list_;
static void language_changed(int cp, void* param);
static const SANE_Device** to_sane_device(ScannerInfo* hgscanner, int count); // 将驱动层传回的设备列表数据转换为标准SANE协议的设备列表
static void free_sane_device(SANE_Device** dev); // 释放由to_sane_device返回的指针
static void device_pnp(int sig); // 热插拔事件监控
static SANE_Fixed double_2_sane_fixed(double v);
static double sane_fixed_2_double(SANE_Fixed v);
void on_device_closed(scanner_handle h);
SANE_Status open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc);
SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, json* jsn, int opt_no);
scanner_handle find_openning_device(SANE_Handle h, bool rmv = false, OPENDEV* dev = NULL);
std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr);
SANE_Option_Descriptor* find_stored_descriptor(const char* name, unsigned long long option);
SANE_Option_Descriptor* find_stored_descriptor(SANE_Handle handle, unsigned long long option);
void reload_current_value(scanner_handle handle, std::vector<std::string>* changed = NULL);
bool get_current_value(scanner_handle handle, int option, void* value, SANE_Value_Type* type = NULL);
void* get_default_value(scanner_handle handle, int option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value
/// <summary>
/// 关联项处理
// 添加对多依赖项的支持 - 2022-03-10
typedef struct _cur_val
{
std::string name;
@ -101,18 +44,6 @@ class hg_sane_middleware
return name == n;
}
}CURVAL;
std::vector<CURVAL> cur_vals_;
bool refresh_current_value(const char* name, json* jsn); // return whether changed old value
bool refresh_current_value(const char* name, const char* val);
static bool compare_val_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_between(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_between(const char* cur_val, const char* limit_l, const char* limit_r);
typedef struct _master_option
{
std::string name;
@ -121,9 +52,6 @@ class hg_sane_middleware
std::string limit_r;
bool(*compare_val)(const char* cur_val, const char* limit_l, const char* limit_r); // ==, !=, >, >=, <, <=, [l, r], ![l, r]
}MASTEROP;
static bool is_enable_and(const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
static bool is_enable_or(const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
typedef struct _slave_option
{
std::string name;
@ -132,14 +60,7 @@ class hg_sane_middleware
bool (*is_enable)(const std::vector<MASTEROP>& master
, std::vector<CURVAL>& curvals/*参数全部字符串化*/); // logic 'and', 'or' opertions
}SLAVEOP;
std::vector<SLAVEOP> slave_options_;
std::vector<std::string> master_options_;
bool parse_master_option(const char* depend_str, MASTEROP& mo);
bool parse_depends(json* jsn, SLAVEOP& so);
typedef struct _opt_enabled
typedef struct _opt_status
{
std::string name;
bool enable;
@ -149,14 +70,124 @@ class hg_sane_middleware
return name == opt;
}
}OPTENABLE;
typedef struct _dev_inst
{
scanner_handle dev;
std::string name;
sane_std_opts* std_opt;
std::vector<DEVOPT> opts;
std::vector<CURVAL> cur_vals;
std::vector<SLAVEOP> slaves;
std::vector<std::string> masters;
bool operator==(const char* n)
{
return strcmp(name.c_str(), n) == 0;
}
bool operator==(scanner_handle h)
{
return dev == h;
}
struct _dev_inst()
{
dev = nullptr;
name = "";
std_opt = nullptr;
}
}DEVINST, * LPDEVINST;
class hg_sane_middleware
{
// std::vector<DEVOPT> opts_;
SANE_Option_Descriptor* opt_0_;
bool init_ok_;
//typedef struct _openning_scanner_option
//{
// std::string dev_name;
// scanner_handle handle;
// int scan_count;
//
// //struct _openning_scanner_option()
// //{
// // dev_name = "";
// // handle = NULL;
// // option_no = 0;
// // desc = NULL;
// //}
// bool operator==(const char* name)
// {
// return strcmp(dev_name.c_str(), name) == 0;
// }
// bool operator==(scanner_handle h)
// {
// return handle == h;
// }
//}OPENDEV;
//std::vector<OPENDEV> openning_;
static hg_sane_middleware *inst_;
static const SANE_Device** dev_list_;
static void language_changed(int cp, void* param);
static const SANE_Device** to_sane_device(ScannerInfo* hgscanner, int count); // 将驱动层传回的设备列表数据转换为标准SANE协议的设备列表
static void free_sane_device(SANE_Device** dev); // 释放由to_sane_device返回的指针
static void device_pnp(int sig); // 热插拔事件监控
static SANE_Fixed double_2_sane_fixed(double v);
static double sane_fixed_2_double(SANE_Fixed v);
static void set_value_to_var(void* val, size_t bytes, void* param);
static void set_value_to_new(void* val, size_t bytes, void* param);
SANE_Status open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc);
SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, json* jsn);
std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr, SANE_Int* id = nullptr);
SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = nullptr);
void reload_current_value(scanner_handle handle, std::vector<std::string>* changed = NULL);
bool get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type = NULL);
void* get_default_value(scanner_handle handle, const void* option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value
/// <summary>
/// 关联项处理
// 添加对多依赖项的支持 - 2022-03-10
//std::vector<CURVAL> cur_vals_;
bool refresh_current_value(LPDEVINST dev, const char* name, json* jsn); // return whether changed old value
bool refresh_current_value(LPDEVINST dev, const char* name, const char* val);
static bool compare_val_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_equal(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_less(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_great(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_between(const char* cur_val, const char* limit_l, const char* limit_r);
static bool compare_val_not_between(const char* cur_val, const char* limit_l, const char* limit_r);
static bool is_enable_and(const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
static bool is_enable_or(const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
//std::vector<SLAVEOP> slave_options_;
//std::vector<std::string> master_options_;
bool parse_master_option(const char* depend_str, MASTEROP& mo);
bool parse_depends(json* jsn, SLAVEOP& so, std::vector<std::string>& master);
bool is_associatived(const SLAVEOP& slave, const char* master_name);
bool set_stored_option_enabled(const char* dev_name, unsigned long long option, bool enable, int* size = NULL);
int something_after_do(scanner_handle h, const char* dev_name, const char* master_name, const char* cur_val);
OPTEN* get_control_enalbe_data(const SLAVEOP& slave);
bool set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size = NULL);
int something_after_do(LPDEVINST dev, const char* master_name, const char* cur_val);
OPTEN* get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave);
void free_control_enable_data(OPTEN* opt);
void on_SCANNER_ERR_CONFIGURATION_CHANGED(scanner_handle handle, const char* dev_name);
void on_SCANNER_ERR_CONFIGURATION_CHANGED(LPDEVINST dev);
std::vector<LPDEVINST> openning_;
std::vector<LPDEVINST>::iterator find_openning_device_in_que(scanner_handle h);
std::vector<LPDEVINST>::iterator find_openning_device_in_que(const char* name);
/// 关联项处理结束
static void free_device_inst(LPDEVINST dev);
scanner_handle find_openning_device(SANE_Handle h, bool rmv = false, LPDEVINST* dev = NULL);
protected:
hg_sane_middleware(void);
~hg_sane_middleware();
@ -177,6 +208,7 @@ public:
, const std::vector<int>& values); // NO constraint if values was empty
static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<double>& values); // NO constraint if values was empty
static std::string get_string_in_json(json* jsn, const char* key);
// methods ...
public:
@ -188,10 +220,11 @@ public:
SANE_Status read(SANE_Handle h, void* buf, int* bytes);
SANE_Status stop(SANE_Handle h);
SANE_Option_Descriptor* get_option_descriptor(SANE_Handle h, SANE_Int option);
SANE_Status set_option(SANE_Handle h, SANE_Int option, SANE_Action action, void* value, SANE_Int* after_do);
bool get_cur_value(SANE_Handle handle, int option, void* value, SANE_Value_Type* type = NULL); // SANE_type
void* get_def_value(SANE_Handle handle, int option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value, SANE_type
SANE_Option_Descriptor* get_option_descriptor(SANE_Handle h, const void* option);
SANE_Status set_option(SANE_Handle h, const void* option, SANE_Action action, void* value, SANE_Int* after_do);
bool get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type = nullptr); // SANE_type
void* get_cur_value(SANE_Handle handle, void* option, SANE_Value_Type* type = nullptr); // caller should call local_utility::free_memory to free the returned value, SANE_type
void* get_def_value(SANE_Handle handle, void* option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value, SANE_type
// extension ...
SANE_Status io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);