增加图像扩展信息接口;增加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

@ -23,8 +23,9 @@ private:
std::condition_variable _condvar; std::condition_variable _condvar;
typedef struct _dq typedef struct _dq
{ {
size_t bytes; size_t bytes;
T t; uint32_t id;
T t;
}DQ; }DQ;
deque<DQ> _queue; deque<DQ> _queue;
size_t bytes_; size_t bytes_;
@ -67,13 +68,13 @@ public:
return isShutDown; 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); lock_guard<mutex> lock(_mutex);
if (!isShutDown) if (!isShutDown)
{ {
{ {
DQ dq = { bytes, task }; DQ dq = { bytes, id, task };
_queue.push_back(dq); _queue.push_back(dq);
bytes_ += bytes; bytes_ += bytes;
} }
@ -82,7 +83,7 @@ public:
} }
T Take() T Take(uint32_t* id = nullptr)
{ {
unique_lock<mutex> lock(_mutex); unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0) if (_queue.size() <= 0)
@ -96,11 +97,13 @@ public:
DQ front(_queue.front()); DQ front(_queue.front());
_queue.pop_front(); _queue.pop_front();
bytes_ -= front.bytes; bytes_ -= front.bytes;
if (id)
*id = front.id;
return front.t; return front.t;
} }
T Front() T Front(uint32_t* id = nullptr)
{ {
unique_lock<mutex> lock(_mutex); unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0) if (_queue.size() <= 0)

View File

@ -786,7 +786,7 @@ void final_img_queue::clear(void)
queue_.clear(); queue_.clear();
} }
bool final_img_queue::put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes 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; IMGDT imgd;
bool ret = false; 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.height = h;
imgd.header.line_bytes = line_bytes; imgd.header.line_bytes = line_bytes;
imgd.header.width = w; imgd.header.width = w;
imgd.header.src_id = id;
imgd.offset = 0; imgd.offset = 0;
imgd.data.reset(new tiny_buffer(bytes, tmp_path, name_leading, ext, ind)); 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 channels;
int line_bytes; int line_bytes;
unsigned bytes; unsigned bytes;
uint32_t src_id;
}IMH; }IMH;
typedef struct _img typedef struct _img
{ {
@ -236,7 +237,7 @@ public:
size_t size(void); size_t size(void);
void clear(void); void clear(void);
bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes 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); bool front(IMH* header);
void fetch_front(void* buf, int* len, bool* over); 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) , 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) , 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) , 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) #if !defined(_WIN32) && !defined(_WIN64) &&defined(x86_64)
isx86_Advan_ = false; isx86_Advan_ = false;
@ -677,7 +677,14 @@ void hg_scanner::get_range(const char* name, std::vector<std::string>& range, st
else else
{ {
std::string v(""); 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); range.push_back(v);
} }
} }
@ -700,8 +707,10 @@ void hg_scanner::get_range(const char* name, std::vector<std::string>& range, st
sprintf(sn, "%f", v); sprintf(sn, "%f", v);
def_val = sn; def_val = sn;
} }
else if(type == "string") 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()); //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) 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); setting_jsn_.at(name).at("type").get_to(val);
if (val == "string") if (val == "string")
{ {
val = ""; val = get_setting_item_string(name, "default");
setting_jsn_.at(name).at("default").get_to(val);
char* buf = NULL; char* buf = NULL;
int size = 0; int size = 0;
@ -913,7 +921,14 @@ bool hg_scanner::get_default_value(void* buf, json* jsn)
else if (type == "string") else if (type == "string")
{ {
type = ""; 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()); strcpy((char*)buf, type.c_str());
} }
else else
@ -943,7 +958,8 @@ void hg_scanner::thread_handle_image_process(void)
continue; continue;
} }
tiny_buffer = imgs_.Take(); uint32_t id = -1;
tiny_buffer = imgs_.Take(&id);
if (tiny_buffer->swap()) if (tiny_buffer->swap())
{ {
try try
@ -956,7 +972,7 @@ void hg_scanner::thread_handle_image_process(void)
stop(); stop();
break; break;
} }
image_process(tiny_buffer); image_process(tiny_buffer, id);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -968,7 +984,7 @@ void hg_scanner::thread_handle_image_process(void)
else else
stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
VLOG_MINI_1(LOG_LEVEL_ALL, "is opencv Fatal: %s\n", e.what()); VLOG_MINI_1(LOG_LEVEL_ALL, "is opencv Fatal: %s\n", e.what());
//stop(); stop();
break; 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)); 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) if(ret == SCANNER_ERR_NOT_EXACT)
// strcpy((char*)data, paper.c_str()); strcpy((char*)data, paper.c_str());
if(old != image_prc_param_.bits.paper) if(old != image_prc_param_.bits.paper)
reset_custom_area_range(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); resolution_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_RESOLUTION, resolution_)) if (!check_range(SANE_STD_OPT_NAME_RESOLUTION, resolution_))
{
*(int*)data = resolution_;
ret = SCANNER_ERR_NOT_EXACT; ret = SCANNER_ERR_NOT_EXACT;
}
// check paper ... // check paper ...
if (!check_paper_and_resolution(resolution_, image_prc_param_.bits.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 hg_scanner::setting_scan_count(void* data)
{ {
int ret = SCANNER_ERR_OK; 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)) if (val == hg_log::lang_load(ID_OPTION_VALUE_SMZS_LXSM))
{ {
scan_count_ = -1; scan_count_ = -1;
@ -2366,11 +2384,32 @@ void hg_scanner::init_settings(const char* json_setting_text)
std::string val(""); 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); setting_jsn_.at(v.c_str()).at("type").get_to(val);
if (val == "string") if (val == "string")
{ {
val = ""; change_string_2_lang_id(v.c_str(), "cur");
setting_jsn_.at(v.c_str()).at("default").get_to(val); 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; char* buf = NULL;
int size = 0; int size = 0;
@ -2421,6 +2460,40 @@ int hg_scanner::init_settings(int pid)
return SCANNER_ERR_OK; 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) int hg_scanner::on_scann_error(int err)
{ {
status_ = 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); 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()) if (wait_img_.is_waiting())
wait_img_.notify(); wait_img_.notify();
} }
@ -2646,7 +2719,7 @@ int hg_scanner::save_usb_data(std::shared_ptr<tiny_buffer> data)
return ret; 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(""); 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.bytes = head->total_bytes;
img.flag.statu = head->statu; img.flag.statu = head->statu;
img.flag.dpi = resolution_; img.flag.dpi = resolution_;
img.src_id = id;
if (img.flag.statu) 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 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; return SCANNER_ERR_OK;
else else
return SCANNER_ERR_INSUFFICIENT_MEMORY; 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) 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("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") if (type == "string")
{ {
setting_jsn_.at(real_n).at("cur") = (char*)data; 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 else
{ {
//json_name.find(real_n) //json_name.find(real_n)
auto it = json_name.find(real_n); //auto it = json_name.find(real_n);
if (it != json_name.end()) //if (it != json_name.end())
{ //{
int i = it->second; // int i = it->second;
//
const char* load = hg_log::lang_load(i); // const char* load = hg_log::lang_load(i);
if (load) // if (*load)
{ // {
setting_jsn_.at(real_n).at("title") = load; // setting_jsn_.at(real_n).at("title") = load;
} // }
//
} //}
std::string text(setting_jsn_.at(real_n).dump()); std::string text(setting_jsn_.at(real_n).dump());
text.insert(0, "\"" + real_n + "\":"); text.insert(0, "\"" + real_n + "\":");
@ -2983,6 +3057,7 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
IMH imh; IMH imh;
fetching_id_ = -1;
bzero(&imh, sizeof(imh)); bzero(&imh, sizeof(imh));
bzero(ii, sizeof(*ii)); bzero(ii, sizeof(*ii));
while ((!wait_img_.is_waiting() || !wait_usb_.is_waiting()) && final_imgs_.size() <= 0) 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)) if (!final_imgs_.front(&imh))
ret = SCANNER_ERR_NO_DATA; ret = SCANNER_ERR_NO_DATA;
else else
{
copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels, imh.bits); 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*/) 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; 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_) 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 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); , 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) int hg_scanner::image_configuration(SCANCONF& ic)

View File

@ -146,7 +146,7 @@ class hg_scanner
void working_begin(void*); void working_begin(void*);
void working_done(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); 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 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); int set_color_change(void);
@ -362,8 +362,12 @@ protected:
int stop_fatal_; int stop_fatal_;
BlockingQueue<std::shared_ptr<tiny_buffer>> imgs_; 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); void init_settings(const char* json_setting_text);
int init_settings(int pid); 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 on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作
int try_third_app_handle_start(bool& handled); int try_third_app_handle_start(bool& handled);
int try_third_app_after_start(int err); 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); 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_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); 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_(""); std::string hg_scanner_mgr::pe_name_("");
bool hg_scanner_mgr::read_over_with_eof_ = true; 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) hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1)
{ {
usb_manager::instance()->register_hotplug(&hg_scanner_mgr::usb_event_handle, this); 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; hg_scanner_mgr::event_callback_ = cb;
if (cb) if (cb)
hg_scanner_mgr::async_io_enabled_ = cb(NULL, SANE_EVENT_SUPPORT_ASYNC_IO, NULL, NULL, NULL) == 0; 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(); 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"); 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_; 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) 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_build_;
static int ver_patch_; static int ver_patch_;
static uint32_t unique_img_id_;
static std::mutex mutex_img_id;
static hg_scanner_mgr* inst_; 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 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_version(int hh, int hl, int lh, int ll);
static void set_exe_name(const char* path, const char* name); static void set_exe_name(const char* path, const char* name);
static std::string get_pe_name(std::string* path = nullptr); 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_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); 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_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 SANE_Status inner_sane_open(SANE_String_Const devicename, SANE_Handle* handle);
extern void inner_sane_close(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 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, SANE_Int option, SANE_Action action, void* value, SANE_Int* info); 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_get_parameters(SANE_Handle handle, SANE_Parameters* params);
extern SANE_Status inner_sane_start(SANE_Handle handle); extern SANE_Status inner_sane_start(SANE_Handle handle);
extern SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length); extern 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_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 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 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> /// <summary>
/// 导出接口 /// 导出接口
@ -51,11 +52,11 @@ void sane_close(SANE_Handle handle)
const SANE_Option_Descriptor* const SANE_Option_Descriptor*
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) 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) 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) 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); 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; hg_sane_middleware* hg_sane_middleware::inst_ = NULL;
const SANE_Device** hg_sane_middleware::dev_list_ = 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) 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() hg_sane_middleware::~hg_sane_middleware()
{ {
register_language_changed_notify(&hg_sane_middleware::language_changed, false); 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) 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(); hg_scanner_uninitialize();
if (opt_0_) if (opt_0_)
local_utility::free_memory(opt_0_); local_utility::free_memory(opt_0_);
if (std_opt_)
delete std_opt_;
} }
void hg_sane_middleware::language_changed(int cp, void* param) 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); 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 hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void* val)
{ {
std::string ret("unknown"); std::string ret("unknown");
@ -486,35 +495,13 @@ std::string hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void
return ret; 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) scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h)
{ {
if (!h)
return nullptr;
int bits = sizeof(h) / 2 * 8; int bits = sizeof(h) / 2 * 8;
unsigned long long v = (unsigned long long)h; uint64_t v = (uint64_t)h;
v ^= v >> bits; 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) SANE_Handle hg_sane_middleware::scanner_handle_to_sane(scanner_handle h)
{ {
if (!h)
return nullptr;
int bits = sizeof(h) / 2 * 8; int bits = sizeof(h) / 2 * 8;
unsigned long long v = (unsigned long long)h; uint64_t v = (uint64_t)h;
v ^= v >> bits; v ^= v >> bits;
@ -753,30 +743,46 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
return sod; return sod;
} }
std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key)
void hg_sane_middleware::on_device_closed(scanner_handle h)
{ {
// 由于ç®å‰<C3A5>对多设备的支æŒ<C3A6>还ä¸<C3A4>是刚需,故代ç <C3A7>å<EFBFBD>ªè€ƒè™å<E28098>•è®¾å¤‡æƒ…况,设备关闭å<C2AD>Žï¼Œæ¸…除所有å<E280B0>˜é‡? std::string str("");
for (size_t i = 0; i < opts_.size(); ++i) 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(); else
for (size_t i = 0; i < openning_.size(); ++i) jsn->get_value(key, str);
{
if (openning_[i].handle == h) return std::move(str);
{
openning_.erase(openning_.begin() + i);
i--;
}
}
cur_vals_.clear();
slave_options_.clear();
master_options_.clear();
if (std_opt_)
delete std_opt_;
std_opt_ = nullptr;
} }
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) 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; 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); err = hg_scanner_open(&h, devicename, false, NULL, NULL, NULL, rsc);
if (err == SCANNER_ERR_OK) if (err == SCANNER_ERR_OK)
{ {
OPENDEV od; LPDEVINST inst = new DEVINST;
od.dev_name = devicename; inst->name = devicename;
od.handle = h; inst->dev = h;
od.scan_count = -1; openning_.push_back(inst);
openning_.push_back(od);
*handle = hg_sane_middleware::scanner_handle_to_sane(h); *handle = hg_sane_middleware::scanner_handle_to_sane(h);
if (!local_utility::cb_ui_) if (!local_utility::cb_ui_)
{ {
long count = 0; long count = 0;
hg_scanner_get_parameter(h, 0, NULL, &count); 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; return SANE_STATUS_GOOD;
@ -812,16 +817,15 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle*
else else
return (SANE_Status)err; // SANE_STATUS_UNSUPPORTED; 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; std::vector<std::string> constraints;
double lower = .0f, upper = .0f, step = .0f; double lower = .0f, upper = .0f, step = .0f;
bool db_val = false; bool db_val = false;
jsn->get_value("title", title);
jsn->get_value("desc", desc);
if (!jsn->get_value("type", val)) if (!jsn->get_value("type", val))
return NULL; return NULL;
@ -836,10 +840,42 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
{ {
if (range->first_child(val)) 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)) 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; delete range;
@ -866,6 +902,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
lower = l; lower = l;
upper = u; upper = u;
step = s; 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() ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, false, &lower, &upper, &step); , 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); range->get_value("max", upper);
step = (upper - lower) / 10.0f; step = (upper - lower) / 10.0f;
range->get_value("step", step); 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() ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
, true, &lower, &upper, &step); , true, &lower, &upper, &step);
} }
@ -977,7 +1015,8 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
} }
if (depend) 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.enable_now = (ret->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE;
so.name = name; so.name = name;
@ -996,13 +1035,13 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
integer = master == "int"; integer = master == "int";
master = ""; master = "";
m->get_value_as_string("cur", master, integer); 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) if (!so.enable_now)
ret->cap |= SANE_CAP_INACTIVE; ret->cap |= SANE_CAP_INACTIVE;
} }
delete m; delete m;
} }
slave_options_.push_back(so); (*it)->slaves.push_back(so);
} }
delete depend; delete depend;
} }
@ -1010,10 +1049,19 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
return ret; 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); 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()) if (it == openning_.end())
handle = NULL; handle = NULL;
@ -1022,12 +1070,16 @@ scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv,
if (dev) if (dev)
*dev = *it; *dev = *it;
if (rmv) if (rmv)
{
if (!dev)
hg_sane_middleware::free_device_inst(*it);
openning_.erase(it); openning_.erase(it);
}
} }
return handle; 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; char* json_txt = NULL;
long length = 0; 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"); json_txt = (char*)local_utility::acquire_memory(ALIGN_INT(length + 4), "hg_sane_middleware::get_option_json");
bzero(json_txt, length + 4); 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) if (err == SCANNER_ERR_OK)
{ {
const char* head = json_txt; const char* head = json_txt;
@ -1068,42 +1120,43 @@ std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt
return ret; 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 (IS_PTR_NUMBER(option)) if (it != openning_.end())
{ {
for (const auto& v : opts_) if (IS_PTR_NUMBER(option))
{ {
if (v.dev_name == name && v.option_no == option) if (id)
return v.desc; *id = (int)option;
for (const auto& v : (*it)->opts)
{
if (v.option_no == (int)option)
return v.desc;
}
} }
} else
else
{
for (const auto& v : opts_)
{ {
if (v.dev_name == name && v.opt_name == (const char*)option) for (const auto& v : (*it)->opts)
return v.desc; {
if (v.opt_name == (const char*)option)
{
if (id)
*id = v.option_no;
return v.desc;
}
}
} }
} }
return NULL; 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) void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector<std::string>* changed)
{ {
long count = 0; long count = 0;
std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
if (changed) if (changed)
changed->clear(); changed->clear();
@ -1116,13 +1169,13 @@ void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector
if (jsn->attach_text(&val[0]) && if (jsn->attach_text(&val[0]) &&
jsn->get_value("type", val)) 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); changed->push_back(key);
} }
delete jsn; 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(""), std::string name(""),
val(get_option_json(handle, (void *)option, &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; int v = 0;
jsn->get_value("cur", v); jsn->get_value("cur", v);
*((SANE_Int*)value) = v; // *((SANE_Int*)value) = v;
setv(&v, sizeof(v), value);
t = SANE_TYPE_INT; t = SANE_TYPE_INT;
} }
else if (val == "bool") else if (val == "bool")
{ {
bool yesorno = false; bool bv = false;
jsn->get_value("cur", yesorno); SANE_Bool v = SANE_FALSE;
*(SANE_Bool*)value = yesorno; jsn->get_value("cur", bv);
// *(SANE_Bool*)value = v;
v = bv;
setv(&v, sizeof(v), value);
t = SANE_TYPE_BOOL; t = SANE_TYPE_BOOL;
} }
else if (val == "float") else if (val == "float")
{ {
double v = .0f; double dv = .0f;
jsn->get_value("cur", v); SANE_Fixed v = 0;
*((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(v); jsn->get_value("cur", dv);
v = hg_sane_middleware::double_2_sane_fixed(dv);
setv(&v, sizeof(v), value);
t = SANE_TYPE_FIXED; t = SANE_TYPE_FIXED;
} }
else else
{ {
val = ""; int size = 0;
jsn->get_value("cur", val); jsn->get_value("size", size);
strcpy((char*)value, val.c_str()); 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(); estimate += val.length();
} }
if (type) if (type)
*type = t; *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); 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()); 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; 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)); std::string val(get_option_json(handle, (void *)option));
void* data = nullptr; void* data = nullptr;
@ -1238,8 +1304,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, int option, i
int size = 0; int size = 0;
jsn->get_value("size", size); jsn->get_value("size", size);
val = ""; val = hg_sane_middleware::get_string_in_json(jsn, "default");
jsn->get_value("default", val);
if (size < (int)val.length()) if (size < (int)val.length())
size = val.length(); size = val.length();
@ -1259,9 +1324,15 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, int option, i
} }
delete jsn; 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; return data;
@ -1332,8 +1403,6 @@ SANE_Status hg_sane_middleware::close_device(SANE_Handle h)
if (hs) if (hs)
err = local_utility::scanner_err_2_sane_statu(hg_scanner_close(hs, true)); err = local_utility::scanner_err_2_sane_statu(hg_scanner_close(hs, true));
if (err == SANE_STATUS_GOOD)
on_device_closed(hs);
return err; 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) SANE_Status hg_sane_middleware::start(SANE_Handle h, void* async_event)
{ {
OPENDEV dev; LPDEVINST dev;
scanner_handle hs = find_openning_device(h, false, &dev); scanner_handle hs = find_openning_device(h);
scanner_err err = SCANNER_ERR_INVALID_PARAMETER; scanner_err err = SCANNER_ERR_INVALID_PARAMETER;
if(hs) 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); 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; 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; SANE_Option_Descriptor* ret = nullptr;
scanner_handle handle = find_openning_device(h, false, &dev); scanner_handle handle = hg_sane_middleware::sane_handle_to_scanner(h);
SANE_Option_Descriptor* ret = NULL; std::vector<LPDEVINST>::iterator it = find_openning_device_in_que(handle);
SANE_Int id = -1;
if (!handle) if (!handle || it == openning_.end())
return NULL; return nullptr;
else if (option == 0)
if (option == 0)
{ {
if (!opt_0_) if (!opt_0_)
{ {
@ -1408,29 +1477,28 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h,
return opt_0_; return opt_0_;
} }
ret = find_stored_descriptor(dev.dev_name.c_str(),option); ret = find_stored_descriptor(handle, option, &id);
if (!ret) if (!ret)
{ {
std::string key(""), 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()) if (json_txt.length())
{ {
json* jsn = new json(); json* jsn = new json();
if (jsn->attach_text(&json_txt[0])) if (jsn->attach_text(&json_txt[0]))
{ {
ret = from_json(handle, key, jsn, option); ret = from_json(handle, key, jsn);
if (ret) if (ret)
{ {
DEVOPT devopt; DEVOPT devopt;
devopt.dev_name = dev.dev_name; devopt.option_no = id;
devopt.option_no = option;
devopt.desc = ret; devopt.desc = ret;
devopt.opt_name = key; devopt.opt_name = std::move(key);
opts_.push_back(devopt); (*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; delete jsn;
@ -1439,17 +1507,17 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h,
if (ret) if (ret)
{ {
if (std_opt_) if ((*it)->std_opt)
std_opt_->init_known_opt(option, ret); (*it)->std_opt->init_known_opt(id, ret);
} }
else if (std_opt_) else if ((*it)->std_opt)
ret = std_opt_->get_option(option); ret = (*it)->std_opt->get_option(id);
return ret; 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); scanner_handle handle = find_openning_device(h, false, &dev);
if (!handle || (action == SANE_ACTION_GET_VALUE && !value)) 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 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; 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; ret = SANE_STATUS_GOOD;
} }
@ -1485,19 +1555,20 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
} }
else 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; bool release_value = false;
scanner_err err = SCANNER_ERR_OK; scanner_err err = SCANNER_ERR_OK;
SANE_Status status = SANE_STATUS_GOOD; SANE_Status status = SANE_STATUS_GOOD;
std::string prev(""), v(""); 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; unsigned char* cont = (unsigned char*)value;
prev = hg_sane_middleware::option_value_2_string(known->type, 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]); 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); v = hg_sane_middleware::option_value_2_string(known->type, value);
} }
else else
@ -1569,16 +1640,16 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
if (err == SCANNER_ERR_OK) 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) 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) 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); 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; err = (scanner_err)SANE_INFO_RELOAD_OPTIONS;
} }
else if (err == SCANNER_ERR_ACCESS_DENIED) 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; 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); scanner_handle h = find_openning_device(handle);
if (!h) if (!h)
return false; 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); 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) SANE_Status hg_sane_middleware::io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len)
{ {
OPENDEV od; LPDEVINST dev;
scanner_handle handle = find_openning_device(h, false, &od); scanner_handle handle = find_openning_device(h, false, &dev);
int ret = SANE_STATUS_GOOD; int ret = SANE_STATUS_GOOD;
// commented at 2022-03-23 for getting app about info before open any device // 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; int nc = code;
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc); 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); 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; 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(""); std::string val(""), mn("");
bool ret = jsn->first_child(val); bool ret = jsn->first_child(val);
@ -1831,10 +1914,10 @@ bool hg_sane_middleware::parse_depends(json* jsn, SLAVEOP& so)
else else
mn = mo.name; mn = mo.name;
so.master.push_back(mo); 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); master.push_back(mo.name);
std::sort(master_options_.begin(), master_options_.end()); std::sort(master.begin(), master.end());
} }
ret = jsn->next_child(val); ret = jsn->next_child(val);
} }
@ -1857,9 +1940,9 @@ bool hg_sane_middleware::is_associatived(const SLAVEOP& slave, const char* maste
return result; 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; bool ret = false;
if (opt) if (opt)
@ -1875,14 +1958,14 @@ bool hg_sane_middleware::set_stored_option_enabled(const char* dev_name, unsigne
return ret; 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; int after = 0;
OPTENABLE oe; OPTENABLE oe;
std::vector<OPTENABLE> changed_options; std::vector<OPTENABLE> changed_options;
refresh_current_value(master_name, cur_val); refresh_current_value(dev, master_name, cur_val);
if (std::find(master_options_.begin(), master_options_.end(), master_name) == master_options_.end()) if (std::find(dev->masters.begin(), dev->masters.end(), master_name) == dev->masters.end())
{ {
return after; 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); changed_options.push_back(oe);
for (size_t i = 0; i < changed_options.size(); ++i) 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 || if (dev->slaves[slave].name == changed_options[i].name ||
!is_associatived(slave_options_[slave], changed_options[i].name.c_str())) !is_associatived(dev->slaves[slave], changed_options[i].name.c_str()))
continue; continue;
bool enable = changed_options[i].enable; bool enable = changed_options[i].enable;
int bytes = 0; int bytes = 0;
// if (enable) // if (enable)
enable = slave_options_[slave].is_enable(slave_options_[slave].master, cur_vals_); enable = dev->slaves[slave].is_enable(dev->slaves[slave].master, dev->cur_vals);
if (enable == slave_options_[slave].enable_now) if (enable == dev->slaves[slave].enable_now)
continue; continue;
slave_options_[slave].enable_now = enable; dev->slaves[slave].enable_now = enable;
if (!set_stored_option_enabled(dev_name, (unsigned long long )slave_options_[slave].name.c_str(), enable, &bytes)) if (!set_stored_option_enabled(dev->dev, dev->slaves[slave].name.c_str(), enable, &bytes))
continue; continue;
OPTEN* op = get_control_enalbe_data(slave_options_[slave]); OPTEN* op = get_control_enalbe_data(dev, dev->slaves[slave]);
hg_scanner_control(h, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL); hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL);
free_control_enable_data(op); 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; continue;
oe.name = slave_options_[slave].name; oe.name = dev->slaves[slave].name;
oe.enable = slave_options_[slave].enable_now; oe.enable = dev->slaves[slave].enable_now;
changed_options.push_back(oe); 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; 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); std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it == cur_vals_.end()) if (it == dev->cur_vals.end())
{ {
CURVAL cv; CURVAL cv;
jsn->get_value("type", cv.type); jsn->get_value("type", cv.type);
cv.name = name; cv.name = name;
jsn->get_value_as_string("cur", cv.val, cv.type == "int"); jsn->get_value_as_string("cur", cv.val, cv.type == "int");
cur_vals_.push_back(cv); dev->cur_vals.push_back(cv);
return false; return false;
} }
@ -1948,10 +2031,10 @@ bool hg_sane_middleware::refresh_current_value(const char* name, json* jsn)
return old != it->val; 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); std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name);
if (it != cur_vals_.end()) if (it != dev->cur_vals.end())
{ {
bool ret = strcmp(it->val.c_str(), val) == 0; 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; 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; std::vector<std::string> master;
OPTEN* opt = NULL; OPTEN* opt = NULL;
@ -1982,8 +2065,8 @@ OPTEN* hg_sane_middleware::get_control_enalbe_data(const SLAVEOP& slave)
opt->master_count = 0; opt->master_count = 0;
for (size_t i = 0; i < master.size(); ++i) for (size_t i = 0; i < master.size(); ++i)
{ {
std::vector<CURVAL>::iterator m = std::find(cur_vals_.begin(), cur_vals_.end(), master[i]); std::vector<CURVAL>::iterator m = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), master[i]);
if (m == cur_vals_.end()) if (m == dev->cur_vals.end())
continue; continue;
opt->master[opt->master_count].name = master[i]; opt->master[opt->master_count].name = master[i];
@ -2020,20 +2103,40 @@ void hg_sane_middleware::free_control_enable_data(OPTEN* opt)
free(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; std::vector<std::string> changed;
reload_current_value(handle, &changed); reload_current_value(dev->dev, &changed);
if (changed.size()) if (changed.size())
{ {
for (size_t i = 0; i < changed.size(); ++i) for (size_t i = 0; i < changed.size(); ++i)
{ {
std::vector<CURVAL>::iterator it = std::find(cur_vals_.begin(), cur_vals_.end(), changed[i]); std::vector<CURVAL>::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), changed[i]);
if (it != cur_vals_.end()) if (it != dev->cur_vals.end())
something_after_do(handle, dev_name, it->name.c_str(), it->val.c_str()); 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>
/// <summary> /// <summary>
@ -2069,11 +2172,11 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
hg_sane_middleware::instance()->close_device(handle); hg_sane_middleware::instance()->close_device(handle);
} }
const SANE_Option_Descriptor* 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); 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); 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)); 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) void sanei_debug_msg(int level, int max_level, const char* be, const char* fmt, va_list ap)
{ {

View File

@ -26,43 +26,105 @@
class json; class json;
class sane_std_opts; 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<MASTEROP> master;
bool (*is_enable)(const std::vector<MASTEROP>& master
, std::vector<CURVAL>& 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<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 class hg_sane_middleware
{ {
typedef struct _device_option // std::vector<DEVOPT> opts_;
{
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_Option_Descriptor* opt_0_;
sane_std_opts* std_opt_;
bool init_ok_; bool init_ok_;
typedef struct _openning_scanner_option //typedef struct _openning_scanner_option
{ //{
std::string dev_name; // std::string dev_name;
scanner_handle handle; // scanner_handle handle;
int scan_count; // int scan_count;
//
//struct _openning_scanner_option() // //struct _openning_scanner_option()
//{ // //{
// dev_name = ""; // // dev_name = "";
// handle = NULL; // // handle = NULL;
// option_no = 0; // // option_no = 0;
// desc = NULL; // // desc = NULL;
//} // //}
bool operator==(const char* name) // bool operator==(const char* name)
{ // {
return strcmp(dev_name.c_str(), name) == 0; // return strcmp(dev_name.c_str(), name) == 0;
} // }
bool operator==(scanner_handle h) // bool operator==(scanner_handle h)
{ // {
return handle == h; // return handle == h;
} // }
}OPENDEV; //}OPENDEV;
std::vector<OPENDEV> openning_; //std::vector<OPENDEV> openning_;
static hg_sane_middleware *inst_; static hg_sane_middleware *inst_;
static const SANE_Device** dev_list_; static const SANE_Device** dev_list_;
@ -73,37 +135,25 @@ class hg_sane_middleware
static void device_pnp(int sig); // 热插拔事件监控 static void device_pnp(int sig); // 热插拔事件监控
static SANE_Fixed double_2_sane_fixed(double v); static SANE_Fixed double_2_sane_fixed(double v);
static double sane_fixed_2_double(SANE_Fixed 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_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); SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, json* jsn);
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_Int* id = nullptr);
std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr); SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = 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); 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); 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, int option, int* bytes = nullptr, bool log = false); // caller should call local_utility::free_memory to free the returned value 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> /// <summary>
/// 关联项处理 /// 关联项处理
// 添加对多依赖项的支持 - 2022-03-10 // 添加对多依赖项的支持 - 2022-03-10
typedef struct _cur_val //std::vector<CURVAL> cur_vals_;
{ bool refresh_current_value(LPDEVINST dev, const char* name, json* jsn); // return whether changed old value
std::string name; bool refresh_current_value(LPDEVINST dev, const char* name, const char* val);
std::string type;
std::string val; /*参数全部字符串化*/
bool operator==(const std::string& n)
{
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_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_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_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_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 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<MASTEROP>& master, std::vector<CURVAL>& curvals); 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); static bool is_enable_or(const std::vector<MASTEROP>& master, std::vector<CURVAL>& curvals);
typedef struct _slave_option //std::vector<SLAVEOP> slave_options_;
{ //std::vector<std::string> master_options_;
std::string name;
bool enable_now;
std::vector<MASTEROP> master;
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_master_option(const char* depend_str, MASTEROP& mo);
bool parse_depends(json* jsn, SLAVEOP& so); bool parse_depends(json* jsn, SLAVEOP& so, std::vector<std::string>& 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 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); bool set_stored_option_enabled(scanner_handle h, const void* 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); int something_after_do(LPDEVINST dev, const char* master_name, const char* cur_val);
OPTEN* get_control_enalbe_data(const SLAVEOP& slave); OPTEN* get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave);
void free_control_enable_data(OPTEN* opt); 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: protected:
hg_sane_middleware(void); hg_sane_middleware(void);
@ -177,6 +208,7 @@ public:
, const std::vector<int>& values); // NO constraint if values was empty , 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 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 , const std::vector<double>& values); // NO constraint if values was empty
static std::string get_string_in_json(json* jsn, const char* key);
// methods ... // methods ...
public: public:
@ -188,10 +220,11 @@ public:
SANE_Status read(SANE_Handle h, void* buf, int* bytes); SANE_Status read(SANE_Handle h, void* buf, int* bytes);
SANE_Status stop(SANE_Handle h); SANE_Status stop(SANE_Handle h);
SANE_Option_Descriptor* get_option_descriptor(SANE_Handle h, SANE_Int option); SANE_Option_Descriptor* get_option_descriptor(SANE_Handle h, const void* option);
SANE_Status set_option(SANE_Handle h, SANE_Int option, SANE_Action action, void* value, SANE_Int* after_do); 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, int option, void* value, SANE_Value_Type* type = NULL); // SANE_type bool get_cur_value(SANE_Handle handle, void* option, void* value, SANE_Value_Type* type = nullptr); // 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 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 ... // extension ...
SANE_Status io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len); SANE_Status io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);