diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index 3b0a16d..e61ed9a 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -668,6 +668,7 @@ void hg_scanner::init_setting_func_map(void) setting_map_[SANE_STD_OPT_NAME_ROLLER_COUNT] = &hg_scanner::setting_get_roller_count; setting_map_[SANE_STD_OPT_NAME_TOTAL_COUNT] = &hg_scanner::setting_get_history_count; setting_map_[SANE_STD_OPT_NAME_GET_DEVS_L0G] = &hg_scanner::setting_get_devs_log; + setting_map_[SANE_STD_OPT_NAME_LANGUAGE] = &hg_scanner::setting_set_language; } std::string hg_scanner::setting_name_from(const char* n_or_id, int* id) { @@ -2495,6 +2496,44 @@ int hg_scanner::setting_get_devs_log(void* data, long* len) strcpy((char*)data, str.c_str()); return ret; } +int hg_scanner::setting_set_language(void* data, long* len) +{ + int err = SCANNER_ERR_OK; + LANATTR **pla = lang_get_supported_languages(); + + if (!pla) + err = SCANNER_ERR_DEVICE_NOT_SUPPORT; + else + { + std::string n(to_default_language((char*)data, nullptr)), now(""); + int id = -1, cur = lang_get_cur_code_page(); + for (int i = 0; pla[i]; ++i) + { + if (pla[i]->cp == cur) + now = pla[i]->name; + if (n == pla[i]->name) + { + id = pla[i]->cp; + break; + } + } + if (id == -1) + { + err = SCANNER_ERR_INVALID_PARAMETER; + strcpy((char*)data, now.c_str()); + } + else if(cur != id) + { + int lid = lang_get_string_id((char*)data, false); + err = SCANNER_ERR_CONFIGURATION_CHANGED; + setting_jsn_.at(SANE_STD_OPT_NAME_LANGUAGE).at("cur") = lid; + lang_set_code_page(id); + on_language_changed(); + } + } + + return err; +} int hg_scanner::on_color_mode_changed(int& color_mode) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; @@ -2647,13 +2686,8 @@ SANE_Image_Statu hg_scanner::last_usb_image_statu(int err) return statu; } -void hg_scanner::init_settings(const char* json_setting_text) +void hg_scanner::change_setting_language(bool init) { - jsn_children_.clear(); - setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text, &jsn_children_); - - VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ...\n", jsn_children_.size() - 1); - notify_setting_result_ = false; for (size_t i = 1; i < jsn_children_.size(); ++i) { std::string v(jsn_children_[i]); @@ -2662,27 +2696,48 @@ 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 (v.compare(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)) == 0) + { + int val = 0; + get_sleep_time(val); + const char* p_time = NULL; + if (val == -1 || val > 20000) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_BXM); // changed in 'if (val == "string")' branch. + else if (val > 0 && val <= 300) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_WFZ); + else if (val > 300 && val <= 600) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_SFZ); + else if (val > 600 && val <= 1800) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_BXS); + else if (val > 1800 && val <= 3600) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_YXS); + else if (val > 3600 && val <= 7200) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_LXS); + else if (val > 7200 && val <= 14400) + p_time = /*from_default_language*/(OPTION_VALUE_XMSJ_SXS); + if (p_time) + setting_jsn_.at(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)).at("default") = p_time; + } if (v.compare(from_default_language(SANE_STD_OPT_NAME_FEED_STRENGTH)) == 0) { int val = 0; on_get_feedmode(val); const char* p_feed = NULL; if (val == 0) - p_feed = from_default_language(OPTION_VALUE_FZQD_R); - else if (val ==1) - p_feed = from_default_language(OPTION_VALUE_FZQD_YB); - else if (val ==2) - p_feed = from_default_language(OPTION_VALUE_FZQD_Q); + p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_R); + else if (val == 1) + p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_YB); + else if (val == 2) + p_feed = /*from_default_language*/(OPTION_VALUE_FZQD_Q); if (p_feed) setting_jsn_.at(from_default_language(SANE_STD_OPT_NAME_TIME_TO_SLEEP)).at("default") = p_feed; - + } if (val == "string") { @@ -2693,7 +2748,7 @@ void hg_scanner::init_settings(const char* json_setting_text) 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) @@ -2704,41 +2759,78 @@ void hg_scanner::init_settings(const char* json_setting_text) setting_jsn_.at(v.c_str()).at("range")[i] = id; } } + if (v.compare(from_default_language(SANE_STD_OPT_NAME_LANGUAGE)) == 0) + continue; - val = get_setting_item_string(v.c_str(), "default"); + if (init) + { + val = get_setting_item_string(v.c_str(), "default"); - char* buf = NULL; - long size = 0; + char* buf = NULL; + long size = 0; - setting_jsn_.at(v.c_str()).at("size").get_to(size); - buf = (char*)malloc(size + 4); - bzero(buf, size + 4); - strcpy(buf, val.c_str()); - set_setting(v.c_str(), buf, &size); - free(buf); + setting_jsn_.at(v.c_str()).at("size").get_to(size); + buf = (char*)malloc(size + 4); + bzero(buf, size + 4); + strcpy(buf, val.c_str()); + set_setting(v.c_str(), buf, &size); + free(buf); + } } - else if (val == "int") + else if (init) { - int n = 0; - long size = sizeof(n); - setting_jsn_.at(v.c_str()).at("default").get_to(n); - set_setting(v.c_str(), (char*)&n, &size); - } - else if (val == "float") - { - double d = .0f; - long size = sizeof(d); - setting_jsn_.at(v.c_str()).at("default").get_to(d); - set_setting(v.c_str(), (char*)&d, &size); - } - else if (val == "bool") - { - bool b = false; - long size = sizeof(b); - setting_jsn_.at(v.c_str()).at("default").get_to(b); - set_setting(v.c_str(), (char*)&b, &size); + if (val == "int") + { + int n = 0; + long size = sizeof(n); + setting_jsn_.at(v.c_str()).at("default").get_to(n); + set_setting(v.c_str(), (char*)&n, &size); + } + else if (val == "float") + { + double d = .0f; + long size = sizeof(d); + setting_jsn_.at(v.c_str()).at("default").get_to(d); + set_setting(v.c_str(), (char*)&d, &size); + } + else if (val == "bool") + { + bool b = false; + long size = sizeof(b); + setting_jsn_.at(v.c_str()).at("default").get_to(b); + set_setting(v.c_str(), (char*)&b, &size); + } } } +} +void hg_scanner::init_settings(const char* json_setting_text) +{ + const char* lang = language_option_descriptor(); + bool empty = true; + + if (lang && *lang) + { + std::string txt(json_setting_text); + size_t pos = txt.rfind('}'); + if (pos != std::string::npos) + { + txt[pos] = ','; + } + if (strstr(lang, "{")) + txt += strstr(lang, "{") + 1; + jsn_children_.clear(); + setting_jsn_ = jsonconfig::load_json_from_text(txt.c_str(), &jsn_children_); + empty = setting_jsn_.empty(); + } + if(empty) + { + jsn_children_.clear(); + setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text, &jsn_children_); + } + + VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ...\n", jsn_children_.size() - 1); + notify_setting_result_ = false; + change_setting_language(true); VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ... OK\n", jsn_children_.size() - 1); if (lang_get_cur_code_page() != DEFAULT_CODE_PAGE) on_language_changed(); @@ -3241,11 +3333,14 @@ int hg_scanner::set_setting(const char* name, void* data, long* len) // setting_jsn_.at(real_n).at("title").get_to(name); if (type == "string") { - int id = lang_get_string_id((char*)data, false); - if (id == -1) - setting_jsn_.at(real_n).at("cur") = (char*)data; - else - setting_jsn_.at(real_n).at("cur") = id; + if (real_n != SANE_STD_OPT_NAME_LANGUAGE) + { + int id = lang_get_string_id((char*)data, false); + if (id == -1) + setting_jsn_.at(real_n).at("cur") = (char*)data; + else + setting_jsn_.at(real_n).at("cur") = id; + } type = (char*)data; } else if (type == "int") diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index 06ada61..4c58017 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -233,7 +233,7 @@ protected: int setting_get_roller_count(void* data, long* len); int setting_get_history_count(void* data, long* len); int setting_get_devs_log(void* data, long* len); - + int setting_set_language(void* data, long* len); virtual void on_device_reconnected(void); virtual int on_scanner_closing(bool force); @@ -374,6 +374,7 @@ protected: uint32_t fetching_id_; // for sane read image ext info. added on 2023-01-13 + void change_setting_language(bool init); 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); diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index 8b1c4cb..648bf81 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -257,12 +257,14 @@ namespace local_utility ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // fixed id map - static void init_fixed_id(const char* name, int id, std::map& mapid) + static void init_fixed_id(const char* name, int id, std::map& mapid, int* fixid = nullptr) { #define TRY_MATCH(n) \ if(strcmp(SANE_STD_OPT_NAME_##n, name) == 0) \ { \ mapid[SANE_OPT_ID_##n] = id; \ + if(fixid) \ + *fixid = SANE_OPT_ID_##n; \ return; \ } TRY_MATCH(IS_MULTI_OUT); @@ -337,6 +339,7 @@ namespace local_utility TRY_MATCH(SEARCH_HOLE_RANGE_B); TRY_MATCH(FOLD_TYPE); TRY_MATCH(COLOR_CORRECTION); + TRY_MATCH(LANGUAGE); //TRY_MATCH(HISTORY_COUNT); //TRY_MATCH(DRIVER_VERSION); @@ -396,6 +399,7 @@ namespace local_utility FIX_ID_TO_NAME(ROLLER_LIFE, sizeof(SANE_Int)); FIX_ID_TO_NAME(CUSTOM_GAMMA, sizeof(SANE_Gamma)); + //FIX_ID_TO_NAME(LANGUAGE, 128); return ""; } @@ -555,8 +559,14 @@ hg_sane_middleware::~hg_sane_middleware() void hg_sane_middleware::language_changed(int cp, void* param) { for (auto& v : hg_sane_middleware::instance()->openning_) + { hg_sane_middleware::free_device_inst(v, false); - + + long count = 0; + hg_scanner_get_parameter(v->dev, nullptr, NULL, &count); + for (long ind = 1; ind < count; ++ind) + hg_sane_middleware::instance()->get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind); + } } const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, int count) { @@ -1295,7 +1305,7 @@ std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt return ret; } -SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id) +SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id, SANE_Int* fix_id) { std::vector::iterator it = find_openning_device_in_que(handle); @@ -1303,12 +1313,33 @@ SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handl { if (IS_PTR_NUMBER(option)) { - if (id) - *id = (SANE_Int)(long long)option; - for (const auto& v : (*it)->opts) + if ((SANE_Int)(long long)option >= SANE_OPT_ID_BASE) { - if (v.option_no == (SANE_Int)(long long)option) - return v.desc; + for (const auto& v : (*it)->opts) + { + if (v.fixed_no == (SANE_Int)(long long)option) + { + if (id) + *id = v.option_no; + if (fix_id) + *fix_id = v.fixed_no; + return v.desc; + } + } + } + else + { + for (const auto& v : (*it)->opts) + { + if (v.option_no == (SANE_Int)(long long)option) + { + if (id) + *id = v.option_no; + if (fix_id) + *fix_id = v.fixed_no; + return v.desc; + } + } } } else @@ -1319,6 +1350,8 @@ SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handl { if (id) *id = v.option_no; + if (fix_id) + *fix_id = v.fixed_no; return v.desc; } } @@ -1511,7 +1544,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o data = local_utility::acquire_memory(size + 4, ""); strcpy((char*)data, val.c_str()); if (bytes) - *bytes = val.length(); + *bytes = val.length() + 1; if (log) { VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "option %d(%s) default value is: %s\n", option, title.c_str(), (char*)data); @@ -1694,8 +1727,12 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, { DEVOPT devopt; devopt.option_no = id; + devopt.fixed_no = 0; devopt.desc = ret; - local_utility::init_fixed_id(key.c_str(), id, (*it)->fixed_id); + if (jsn->get_value("fix-id", devopt.fixed_no)) + (*it)->fixed_id[(sane_option_id)devopt.fixed_no] = id; + else + local_utility::init_fixed_id(key.c_str(), id, (*it)->fixed_id, &devopt.fixed_no); devopt.opt_name = std::move(key); (*it)->opts.push_back(std::move(devopt)); @@ -1774,6 +1811,19 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA return SANE_STATUS_GOOD; } + else if (action == SANE_ACTION_GET_FIX_ID) + { + SANE_Int id = 0; + find_stored_descriptor(handle, option, nullptr, &id); + if (id > SANE_OPT_ID_BASE) + { + *(SANE_Int*)value = id; + + return SANE_STATUS_GOOD; + } + else + return SANE_STATUS_UNSUPPORTED; + } else if(action == SANE_ACTION_SET_AUTO || action == SANE_ACTION_SET_VALUE) { SANE_Int id = -1; @@ -1781,16 +1831,36 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA bool release_value = false; scanner_err err = SCANNER_ERR_OK; SANE_Status status = SANE_STATUS_GOOD; - std::string prev(""), v(""); + std::string prev(""), v(""), desc_name(""), desc_title(""); + SANE_Value_Type sane_type = SANE_TYPE_BUTTON; + + if (desc) + { + desc_name = desc->name; + desc_title = desc->title; + sane_type = desc->type; + } if (action == SANE_ACTION_SET_AUTO && desc && desc->type != SANE_TYPE_BUTTON && desc->type != SANE_TYPE_GROUP) // we assume the driver can set the option properbly, and no work to do { VLOG_MINI_2(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title); - value = get_default_value(handle, option); - if (!value) + int len = 0; + void* val = get_default_value(handle, option, &len); + + if (!val) return SANE_STATUS_UNSUPPORTED; - release_value = true; + + if (value) + { + memcpy(value, val, len); + local_utility::free_memory(val); + } + else + { + value = val; + release_value = true; + } } if (dev->std_opt && dev->std_opt->is_known_option(id, &desc)) @@ -1856,50 +1926,50 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA size = sizeof(dv); } - err = hg_scanner_set_parameter(handle, (const char*)option, pass, &size); + err = hg_scanner_set_parameter(handle, (const char*)option, pass, &size); // NOTE: change language will lead 'desc' reallocated !!! - if (desc->type == SANE_TYPE_BOOL) + if (sane_type == SANE_TYPE_BOOL) { *((SANE_Bool*)value) = bv ? SANE_TRUE : SANE_FALSE; } - else if (desc->type == SANE_TYPE_FIXED) + else if (sane_type == SANE_TYPE_FIXED) { *((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(dv); } - v = hg_sane_middleware::option_value_2_string(desc->type, value); + v = hg_sane_middleware::option_value_2_string(sane_type, value); } if (prev == v) { - VLOG_MINI_3(LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc->title, v.c_str()); + VLOG_MINI_3(LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc_title.c_str(), v.c_str()); } else { - VLOG_4(LOG_LEVEL_ALL, 512, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc->title, prev.c_str(), v.c_str()); + VLOG_4(LOG_LEVEL_ALL, 512, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc_title.c_str(), prev.c_str(), v.c_str()); } if (err == SCANNER_ERR_OK) { - err = (scanner_err)something_after_do(dev, desc->name, v.c_str()); + err = (scanner_err)something_after_do(dev, desc_name.c_str(), v.c_str()); } else if (err == SCANNER_ERR_NOT_EXACT) { - err = (scanner_err)(something_after_do(dev, desc->name, v.c_str()) | SANE_INFO_INEXACT); + err = (scanner_err)(something_after_do(dev, desc_name.c_str(), 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); + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects other options value, RELOAD ...\n", desc_title.c_str()); on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); err = (scanner_err)SANE_INFO_RELOAD_OPTIONS; } else if(err == SCANNER_ERR_RELOAD_IMAGE_PARAM) { - VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter, APP should re-get ...\n", desc->title); + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter, APP should re-get ...\n", desc_title.c_str()); err = (scanner_err)SANE_INFO_RELOAD_PARAMS; } else if(err == SCANNER_ERR_RELOAD_OPT_PARAM) { - VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter and options, APP should re-get image info and reload options...\n", desc->title); + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "the setting '%s' affects image parameter and options, APP should re-get image info and reload options...\n", desc_title.c_str()); on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); err = (scanner_err)(SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS); } diff --git a/hgsane/sane_hg_mdw.h b/hgsane/sane_hg_mdw.h index a451ed5..6ab5f0c 100644 --- a/hgsane/sane_hg_mdw.h +++ b/hgsane/sane_hg_mdw.h @@ -31,6 +31,7 @@ typedef struct _device_option { // std::string dev_name; int option_no; + int fixed_no; // 固定ID std::string opt_name; SANE_Option_Descriptor* desc; }DEVOPT; @@ -143,7 +144,7 @@ class hg_sane_middleware SANE_Status open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc); SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, json* jsn); std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr, SANE_Int* id = nullptr); - SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = nullptr); + SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = nullptr, SANE_Int* fix_id = nullptr); void reload_current_value(scanner_handle handle, std::vector* changed = NULL); bool get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type = NULL);