diff --git a/sane/s2t_api.h b/sane/s2t_api.h index c1372a5..fac22e1 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -38,6 +38,9 @@ enum value_limit VAL_LIMIT_NONE = 0, // VAL_LIMIT_ENUM, // VAL_LIMIT_RANGE, // + + VAL_LIMIT_MASK = 0x0ff, + VAL_LIMIT_READONLY = 0x100, }; enum value_role { @@ -55,6 +58,7 @@ enum value_type VAL_TYPE_INT, // int VAL_TYPE_FLOAT, // float VAL_TYPE_STR, // char* + VAL_TYPE_STREAM, // uint8_t[], must give array length VAL_TYPE_BUTTON, // a button }; enum color_value // 除最后一项外,其余与Twpp::PixelType值保持一致 @@ -177,6 +181,7 @@ struct __declspec(novtable) ISaneInvoker : public IRef COM_API_DECLARE(int, set_value(int sn, void* val)); COM_API_DECLARE(int, convert_image(SANE_ImageFormatConvert* conv)); COM_API_DECLARE(void, free_buffer(void* buf, int len)); + COM_API_DECLARE(int, get_fixed_ids(bool(__stdcall* cb)(uint32_t id, void* param), void* param)); // SANE options ID ... SANE_OPTION_ID_API(color_correction); // 2023-02-24 15:31:19 色偏校正 diff --git a/sane/sane_option_trans.cpp b/sane/sane_option_trans.cpp index 7d58da7..4fc7979 100644 --- a/sane/sane_option_trans.cpp +++ b/sane/sane_option_trans.cpp @@ -3,6 +3,13 @@ #include #include "../../sdk/include/lang/app_language.h" +// #include +enum Language // copy from +{ + English = 2, + ChineseSimplified = 41, + ChineseTraditional = 43, +}; namespace sane_opt_trans { @@ -57,6 +64,10 @@ namespace sane_opt_trans , {PAPER_MAXSIZE_CROP, OPTION_VALUE_ZZCC_ZDSMCCZDCQ} , {PAPER_DOUBLE_LETTER, OPTION_VALUE_ZZCC_DoubleLetter} , {PAPER_TRIPPLE, OPTION_VALUE_ZZCC_SLSJ} + }, + g_language[] = { {Language::ChineseSimplified, "\344\270\255\346\226\207\357\274\210\347\256\200\344\275\223\357\274\211"} + , {Language::ChineseTraditional, "\344\270\255\346\226\207\357\274\210\347\271\201\344\275\223\357\274\211"} + , {Language::English, "\350\213\261\350\257\255"} } ; #define VALUE_FROM_TWAIN(arr, val) \ @@ -299,5 +310,19 @@ namespace sane_opt_trans return it; } + + int language_to_twain(const char* language) + { + VALUE_TO_TWAIN(g_language, language); + + return Language::ChineseSimplified; + } + const char* language_from_twain(int language) + { + VALUE_FROM_TWAIN(g_language, language); + + VALUE_FROM_TWAIN(g_language, Language::ChineseSimplified); + } + } diff --git a/sane/sane_option_trans.h b/sane/sane_option_trans.h index 72dbac2..347cf88 100644 --- a/sane/sane_option_trans.h +++ b/sane/sane_option_trans.h @@ -37,5 +37,8 @@ namespace sane_opt_trans int compression_to_twain(int val); std::vector support_image_types(void); + + int language_to_twain(const char* language); + const char* language_from_twain(int language); } diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 75eed6a..c47bb34 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -912,7 +912,8 @@ int scanner::open(void) // check roller life ... SANE_Int cnt = 0, life = 0; if (hg_sane_middleware::instance()->get_cur_value(handle_, (void*)SANE_OPT_ID_ROLLER_COUNT, &cnt) && - hg_sane_middleware::instance()->get_cur_value(handle_, (void*)SANE_OPT_ID_ROLLER_LIFE, &life)) + hg_sane_middleware::instance()->set_option(handle_, (void*)SANE_OPT_ID_ROLLER_LIFE, SANE_ACTION_GET_VALUE, &life, NULL) == SANE_STATUS_GOOD) + //hg_sane_middleware::instance()->get_cur_value(handle_, (void*)SANE_OPT_ID_ROLLER_LIFE, &life)) { if (cnt >= life) { @@ -993,6 +994,8 @@ int scanner::init_options_id(void) INIT_FIXED_IDS(DRIVER_LOG); INIT_FIXED_IDS(DEVICE_LOG); INIT_FIXED_IDS(ROLLER_LIFE); + INIT_FIXED_IDS(DEVICE_MAC_ADDR); + INIT_FIXED_IDS(CUSTOM_GAMMA); while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (const void*)op_id))) { @@ -1102,6 +1105,7 @@ int scanner::init_options_id(void) else SET_OPT_ID(search_hole_range_b, SEARCH_HOLE_RANGE_B, extension_none) else SET_OPT_ID(fold_direction, FOLD_TYPE, extension_none) else SET_OPT_ID(color_correction, COLOR_CORRECTION, extension_none) + else SET_OPT_ID(language, LANGUAGE, extension_none) op_id++; } @@ -2680,25 +2684,25 @@ COM_API_IMPLEMENT(scanner, int, image_fetched(IScanImg* tx)) COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes)) { -#define SIMPLE_STR_INFO(id) \ +#define SIMPLE_STR_INFO(id, rdo) \ if (sn == id) \ { \ if (type) \ *type = VAL_TYPE_STR; \ if (limit) \ - *limit = VAL_LIMIT_NONE; \ + *limit = rdo ? VAL_LIMIT_READONLY : VAL_LIMIT_NONE; \ if (bytes) \ *bytes = 255; \ \ return true; \ } -#define SIMPLE_INT_INFO(id) \ +#define SIMPLE_INT_INFO(id, rdo) \ if (sn == id) \ { \ if (type) \ *type = VAL_TYPE_INT; \ if (limit) \ - *limit = VAL_LIMIT_NONE; \ + *limit = rdo ? VAL_LIMIT_READONLY : VAL_LIMIT_NONE; \ if (bytes) \ *bytes = sizeof(int); \ \ @@ -2706,25 +2710,27 @@ COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value } - SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_VERSION); - SIMPLE_STR_INFO(SANE_OPT_ID_MANUFACTURER); - SIMPLE_STR_INFO(SANE_OPT_ID_COPYRIGHT); - SIMPLE_STR_INFO(SANE_OPT_ID_CO_URL); - SIMPLE_STR_INFO(SANE_OPT_ID_CO_TEL); - SIMPLE_STR_INFO(SANE_OPT_ID_CO_ADDR); - SIMPLE_STR_INFO(SANE_OPT_ID_CO_GPS); - SIMPLE_STR_INFO(SANE_OPT_ID_DEV_NAME); - SIMPLE_STR_INFO(SANE_OPT_ID_DEV_FAMILY); - SIMPLE_STR_INFO(SANE_OPT_ID_LOGIN); - SIMPLE_STR_INFO(SANE_OPT_ID_LOGOUT); - SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_LOG); - SIMPLE_STR_INFO(SANE_OPT_ID_DEVICE_LOG); + SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_VERSION, true); + SIMPLE_STR_INFO(SANE_OPT_ID_MANUFACTURER, true); + SIMPLE_STR_INFO(SANE_OPT_ID_COPYRIGHT, true); + SIMPLE_STR_INFO(SANE_OPT_ID_CO_URL, true); + SIMPLE_STR_INFO(SANE_OPT_ID_CO_TEL, true); + SIMPLE_STR_INFO(SANE_OPT_ID_CO_ADDR, true); + SIMPLE_STR_INFO(SANE_OPT_ID_CO_GPS, true); + SIMPLE_STR_INFO(SANE_OPT_ID_DEV_NAME, true); + SIMPLE_STR_INFO(SANE_OPT_ID_DEV_FAMILY, true); + SIMPLE_STR_INFO(SANE_OPT_ID_LOGIN, false); + SIMPLE_STR_INFO(SANE_OPT_ID_LOGOUT, false); + SIMPLE_STR_INFO(SANE_OPT_ID_DRIVER_LOG, false); + SIMPLE_STR_INFO(SANE_OPT_ID_DEVICE_LOG, false); + SIMPLE_STR_INFO(SANE_OPT_ID_DEVICE_MAC_ADDR, true); - SIMPLE_INT_INFO(SANE_OPT_ID_HELP); - SIMPLE_INT_INFO(SANE_OPT_ID_HISTORY_COUNT); - SIMPLE_INT_INFO(SANE_OPT_ID_ROLLER_COUNT); - SIMPLE_INT_INFO(SANE_OPT_ID_VID); - SIMPLE_INT_INFO(SANE_OPT_ID_PID); + SIMPLE_INT_INFO(SANE_OPT_ID_HELP, false); + SIMPLE_INT_INFO(SANE_OPT_ID_HISTORY_COUNT, true); + SIMPLE_INT_INFO(SANE_OPT_ID_ROLLER_COUNT, false); + SIMPLE_INT_INFO(SANE_OPT_ID_VID, true); + SIMPLE_INT_INFO(SANE_OPT_ID_PID, true); + SIMPLE_INT_INFO(SANE_OPT_ID_ROLLER_LIFE, true); sn = transfer_id(sn); if (sn == -1) @@ -2739,7 +2745,12 @@ COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value if (type) *type = scanner::from_sane_type(desc->type); if (limit) - *limit = scanner::from_sane_constraint(desc->constraint_type); + { + int lmt = scanner::from_sane_constraint(desc->constraint_type); + if (IS_CAP_READONLY(desc->cap)) + lmt |= VAL_LIMIT_READONLY; + *limit = (value_limit)lmt; + } if (bytes) *bytes = desc->size; @@ -2774,7 +2785,11 @@ COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* p return false; } - sn = transfer_id(sn); + int org_id = sn; + if(sn == 0x102c) // CapType::Language + sn = transfer_id(SANE_OPT_ID_LANGUAGE); + else + sn = transfer_id(sn); if (sn == -1) return false; @@ -2904,7 +2919,14 @@ COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* p role = value_role(role | VAL_ROLE_DEFAULT); val = desc->constraint.string_list[i]; - if (!setval(&val, role, VAL_LIMIT_ENUM, param)) + if (org_id == 0x102c) + { + // const char* hz = local_trans::lang_trans_between_hz936(val.c_str(), false, NULL); + int lid = sane_opt_trans::language_to_twain(val.c_str()); + if (!setval(&lid, role, VAL_LIMIT_ENUM, param)) + break; + } + else if (!setval(&val, role, VAL_LIMIT_ENUM, param)) break; } } @@ -2943,7 +2965,11 @@ COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val)) return ret; } - sn = transfer_id(sn); + int org_id = sn; + if (sn == 0x102c) // CapType::Language + sn = transfer_id(SANE_OPT_ID_LANGUAGE); + else + sn = transfer_id(sn); if (sn == -1) return SANE_STATUS_UNSUPPORTED; @@ -2967,8 +2993,17 @@ COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val)) twain_set_ = true; if (ex == ex_opts_.end()) { - if (!set_option_value_with_parent(sn, val, &ret)) - ret = set_option_value(sn, desc->type, desc->size, val); + std::string strv(""); + void* w = val; + if (org_id == 0x102c) + { + const char* str = sane_opt_trans::language_from_twain(*(int*)val); + strv = str; + w = &strv; + } + + if (!set_option_value_with_parent(sn, w, &ret)) + ret = set_option_value(sn, desc->type, desc->size, w); ret = local_utility::sane_statu_2_scanner_err(ret); } else @@ -2994,6 +3029,16 @@ COM_API_IMPLEMENT(scanner, void, free_buffer(void* buf, int len)) { hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_FREE_MEMORY, buf, (unsigned int*)&len); } +COM_API_IMPLEMENT(scanner, int, get_fixed_ids(bool(__stdcall* cb)(uint32_t id, void* param), void* param)) +{ + for (auto& v : sane_ids_) + { + if (!cb(v.first, param)) + break; + } + + return 0; +} // SANE options ID ... SANE_OPTION_ID_IMPLEMENT(color_correction) diff --git a/sane/scanner.h b/sane/scanner.h index 4eb4f1f..b33f2a6 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -69,7 +69,7 @@ class scanner : public ISaneInvoker, virtual public refer gb::scanner_cfg* cfg_; bool twain_set_; SANEAPI sane_api_; - std::map sane_ids_; + std::map sane_ids_; // std::function ui_notify; int(__stdcall* scanner_ev_handler_)(int, void*); void* evh_param_; @@ -228,6 +228,7 @@ public: COM_API_OVERRIDE(int, set_value(int sn, void* val)); COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv)); COM_API_OVERRIDE(void, free_buffer(void* buf, int len)); + COM_API_OVERRIDE(int, get_fixed_ids(bool(__stdcall* cb)(uint32_t id, void* param), void* param)); // SANE options ID ... SANE_OPTION_ID(color_correction); // 2023-02-24 15:31:19 色偏校正 @@ -331,6 +332,8 @@ public: SANE_OPTION_ID(ex_hardware_version); // std::string SANE_OPTION_ID(ex_ip); // std::string + int language_id_; + // ui ... COM_API_OVERRIDE(bool, ui_show_main(HWND parent)); COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true)); diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index bedc467..90f57b0 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -764,6 +764,14 @@ static void log_attr_access(int attr, int method) load_sane_util::log_info(msg, method == (int)Msg::Set || method == (int)Msg::Reset); } +// get fixed-ids from SANE option ... +static bool __stdcall got_fixed_id(uint32_t id, void* param) +{ + ((std::vector*)param)->push_back(id); + + return true; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // huagao_ds ... #include "../../../sdk/include/huagao/brand.h" @@ -1878,6 +1886,46 @@ void huagao_ds::init_support_caps(void) return CapSupGetAllReset(msg, data, { Compression::None, Compression::Group4 }, m_compression, Compression::None, m_compression == Compression::None ? 0 : 1, 0); }; + if (scanner_->get_option_info(SANE_OPT_ID_LANGUAGE, NULL, NULL, NULL)) + { + m_query[CapType::Language] = msgSupportGetAllSetReset; + m_caps[CapType::Language] = [this](/*Twpp::CapType type, */Msg msg, Capability& data)->Result { + log_attr_access((int)CapType::ICompression, (int)msg); + std::vector all; + if (!scanner_.get()) + return seqError(); + + sane_opts::get_opts op(NULL, &all); + int sn = (int)CapType::Language; // SANE_OPT_ID_LANGUAGE; + scanner_->get_value(sn, sane_opts::set_opt_value, &op); + op.re_order(); + + if (Msg::Set == msg || Msg::Reset == msg) { + int mech = (int)data.currentItem(); + if (Msg::Reset == msg) + mech = all[sane_opts::RANGE_POS_DEFAULT]; + + int ret = scanner_->set_value(sn, &mech); + if (ret) + return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(ret) }; + else + return success(); + } + UInt16 cur = all[sane_opts::RANGE_POS_CURRENT], init = all[sane_opts::RANGE_POS_DEFAULT]; + int ni = 0, ii = 0; + std::list alll; + for (int i = 0; i < all.size() - sane_opts::RANGE_POS_ENUM_BEGIN; ++i) + { + if (all[i + sane_opts::RANGE_POS_ENUM_BEGIN] == cur) + ni = i; + else if (all[i + sane_opts::RANGE_POS_ENUM_BEGIN] == init) + ii = i; + alll.push_back(all[i + sane_opts::RANGE_POS_ENUM_BEGIN]); + } + return cap_get_enum_values(msg, data, alll, cur, init, ni, ii); + }; + } + m_query[CapType::IUnits] = msgSupportGetAllSetReset; m_caps[CapType::IUnits] = std::bind(enmGetSetConst, _1, _2, Unit::Inches);