diff --git a/hgdriver/hgdev/BlockingQueue.h b/hgdriver/hgdev/BlockingQueue.h index 1aa2d23..b877bb0 100644 --- a/hgdriver/hgdev/BlockingQueue.h +++ b/hgdriver/hgdev/BlockingQueue.h @@ -23,8 +23,9 @@ private: std::condition_variable _condvar; typedef struct _dq { - size_t bytes; - T t; + size_t bytes; + uint32_t id; + T t; }DQ; deque _queue; size_t bytes_; @@ -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 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 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 lock(_mutex); if (_queue.size() <= 0) diff --git a/hgdriver/hgdev/hg_ipc.cpp b/hgdriver/hgdev/hg_ipc.cpp index 9bf1978..bc10c3d 100644 --- a/hgdriver/hgdev/hg_ipc.cpp +++ b/hgdriver/hgdev/hg_ipc.cpp @@ -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)); diff --git a/hgdriver/hgdev/hg_ipc.h b/hgdriver/hgdev/hg_ipc.h index 06db0cd..5226fa5 100644 --- a/hgdriver/hgdev/hg_ipc.h +++ b/hgdriver/hgdev/hg_ipc.h @@ -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); }; \ No newline at end of file diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index 134377e..5d52887 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -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,7 +677,14 @@ void hg_scanner::get_range(const char* name, std::vector& range, st else { std::string v(""); - setting_jsn_.at(name).at("range").at(i).get_to(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); } } @@ -700,8 +707,10 @@ void hg_scanner::get_range(const char* name, std::vector& range, st sprintf(sn, "%f", v); def_val = sn; } - else if(type == "string") - setting_jsn_.at(name).at("default").get_to(def_val); + else if (type == "string") + { + 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,7 +921,14 @@ bool hg_scanner::get_default_value(void* buf, json* jsn) else if (type == "string") { type = ""; - jsn->at("default").get_to(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()); } else @@ -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; @@ -2365,12 +2383,33 @@ void hg_scanner::init_settings(const char* json_setting_text) continue; 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 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 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& buffer) +void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id) { if (!buffer.get() || !ImagePrc_pHandle_) { @@ -3919,7 +3997,10 @@ void hg_scanner::image_process(std::shared_ptr& 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) diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index 2e5f9fe..cd685c9 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -146,7 +146,7 @@ class hg_scanner void working_begin(void*); void working_done(void*); - void image_process(std::shared_ptr& buff); + void image_process(std::shared_ptr& 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> 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 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); diff --git a/hgdriver/hgdev/scanner_manager.cpp b/hgdriver/hgdev/scanner_manager.cpp index 33a32f1..79eaaaf 100644 --- a/hgdriver/hgdev/scanner_manager.cpp +++ b/hgdriver/hgdev/scanner_manager.cpp @@ -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 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) { diff --git a/hgdriver/hgdev/scanner_manager.h b/hgdriver/hgdev/scanner_manager.h index 7cb22a8..b7fd52f 100644 --- a/hgdriver/hgdev/scanner_manager.h +++ b/hgdriver/hgdev/scanner_manager.h @@ -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); diff --git a/hgsane/main.c b/hgsane/main.c index 5314851..0eebb09 100644 --- a/hgsane/main.c +++ b/hgsane/main.c @@ -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); /// /// 导出接口 @@ -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); +} diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index ec33466..82dc360 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -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; } - -void hg_sane_middleware::on_device_closed(scanner_handle h) +std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key) { - // 由于目前对多设备的支持还不是刚需,故代码只考虑单设备情况,设备关闭后,清除所有变? - for (size_t i = 0; i < opts_.size(); ++i) + std::string str(""); + int id = -1; + + if (jsn->get_value(key, id) && id != -1) { - local_utility::free_memory(opts_[i].desc); + str = lang_load_string(id, &id); } - opts_.clear(); - for (size_t i = 0; i < openning_.size(); ++i) - { - if (openning_[i].handle == h) - { - openning_.erase(openning_.begin() + i); - i--; - } - } - cur_vals_.clear(); - slave_options_.clear(); - master_options_.clear(); - if (std_opt_) - delete std_opt_; - std_opt_ = nullptr; + else + jsn->get_value(key, str); + + return std::move(str); } + +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; + } +} + 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 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,10 +840,42 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st { if (range->first_child(val)) { - constraints.push_back(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)) { - constraints.push_back(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); } } delete range; @@ -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::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::iterator it = std::find(openning_.begin(), openning_.end(), handle); + std::vector::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) { - - if (IS_PTR_NUMBER(option)) + std::vector::iterator it = find_openning_device_in_que(handle); + + if (it != openning_.end()) { - for (const auto& v : opts_) + if (IS_PTR_NUMBER(option)) { - if (v.dev_name == name && v.option_no == option) - return v.desc; + if (id) + *id = (int)option; + for (const auto& v : (*it)->opts) + { + if (v.option_no == (int)option) + return v.desc; + } } - } - else - { - for (const auto& v : opts_) + else { - if (v.dev_name == name && v.opt_name == (const char*)option) - return v.desc; + for (const auto& v : (*it)->opts) + { + 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* changed) { long count = 0; + std::vector::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::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::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); - scanner_err err = SCANNER_ERR_INVALID_PARAMETER; + 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::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& 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 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::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), name); - if (it == cur_vals_.end()) + std::vector::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::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), name); - if (it != cur_vals_.end()) + std::vector::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 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::iterator m = std::find(cur_vals_.begin(), cur_vals_.end(), master[i]); - if (m == cur_vals_.end()) + std::vector::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 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::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::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::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::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(); +} /// /// @@ -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) { diff --git a/hgsane/sane_hg_mdw.h b/hgsane/sane_hg_mdw.h index 1557361..9d7ac2e 100644 --- a/hgsane/sane_hg_mdw.h +++ b/hgsane/sane_hg_mdw.h @@ -26,43 +26,105 @@ class json; class sane_std_opts; +typedef struct _device_option +{ + // std::string dev_name; + int option_no; + std::string opt_name; + SANE_Option_Descriptor* desc; +}DEVOPT; +typedef struct _cur_val +{ + std::string name; + std::string type; + std::string val; /*参数全部字符串化*/ + + bool operator==(const std::string& n) + { + return name == n; + } +}CURVAL; +typedef struct _master_option +{ + std::string name; + SANE_Value_Type type; + std::string limit_l; + std::string limit_r; + bool(*compare_val)(const char* cur_val, const char* limit_l, const char* limit_r); // ==, !=, >, >=, <, <=, [l, r], ![l, r] +}MASTEROP; +typedef struct _slave_option +{ + std::string name; + bool enable_now; + std::vector master; + bool (*is_enable)(const std::vector& master + , std::vector& curvals/*参数全部字符串化*/); // logic 'and', 'or' opertions +}SLAVEOP; +typedef struct _opt_status +{ + std::string name; + bool enable; + + bool operator==(const std::string& opt) + { + return name == opt; + } +}OPTENABLE; +typedef struct _dev_inst +{ + scanner_handle dev; + std::string name; + sane_std_opts* std_opt; + std::vector opts; + std::vector cur_vals; + std::vector slaves; + std::vector 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 { - typedef struct _device_option - { - std::string dev_name; - int option_no; - std::string opt_name; - SANE_Option_Descriptor* desc; - }DEVOPT; - std::vector opts_; + // std::vector 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 openning_; + //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 openning_; static hg_sane_middleware *inst_; static const SANE_Device** dev_list_; @@ -73,37 +135,25 @@ class hg_sane_middleware 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); - 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); + 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* 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 + 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 /// /// 关联项处理 // 添加对多依赖项的支持 - 2022-03-10 - typedef struct _cur_val - { - std::string name; - std::string type; - std::string val; /*参数全部字符串化*/ - - bool operator==(const std::string& n) - { - return name == n; - } - }CURVAL; - std::vector 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); + //std::vector 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); @@ -113,49 +163,30 @@ class hg_sane_middleware 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; - SANE_Value_Type type; - std::string limit_l; - 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& master, std::vector& curvals); static bool is_enable_or(const std::vector& master, std::vector& curvals); - typedef struct _slave_option - { - std::string name; - bool enable_now; - std::vector master; - bool (*is_enable)(const std::vector& master - , std::vector& curvals/*参数全部字符串化*/); // logic 'and', 'or' opertions - }SLAVEOP; - std::vector slave_options_; - std::vector master_options_; + //std::vector slave_options_; + //std::vector master_options_; bool parse_master_option(const char* depend_str, MASTEROP& mo); - bool parse_depends(json* jsn, SLAVEOP& so); + bool parse_depends(json* jsn, SLAVEOP& so, std::vector& master); - typedef struct _opt_enabled - { - std::string name; - bool enable; - - bool operator==(const std::string& opt) - { - return name == opt; - } - }OPTENABLE; 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 openning_; + std::vector::iterator find_openning_device_in_que(scanner_handle h); + std::vector::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); @@ -177,6 +208,7 @@ public: , const std::vector& 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& 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);