From d4d4d969a893b9c836e5d13fc15ec3e3f3bd1456 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Tue, 28 Mar 2023 15:02:24 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=89=AB=E6=8F=8F=E4=BB=AA?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86=E4=B8=8ETWAIN=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9C=BA=E4=B9=8B=E9=97=B4=E7=9A=84=E5=8D=8F=E5=90=8C?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=8C=E5=85=BC=E5=AE=B9=E5=A5=BD=E5=88=86?= =?UTF-8?q?=E6=95=B0=E5=90=AF=E5=8A=A8=E6=89=AB=E6=8F=8F=E5=90=8E=E6=97=A0?= =?UTF-8?q?DSEntry=E8=B0=83=E7=94=A8=E5=8F=8A=E4=BA=91=E9=98=85=E5=8D=B7?= =?UTF-8?q?=E4=B8=8D=E7=AD=89=E7=8A=B6=E6=80=81=E6=94=B9=E5=8F=98=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=8F=96=E5=9B=BE=E2=80=A6=E2=80=A6=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E5=A4=8D=E4=B8=8A=E4=B8=80=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=B8=8D=E6=98=BE=E7=A4=BA=E8=BF=9B=E5=BA=A6=E6=8C=87=E7=A4=BA?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E5=AF=BC=E8=87=B4=E5=B7=A5=E4=BD=9C=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=89=AB=E6=8F=8F=E4=BB=AA=E4=BA=8B=E4=BB=B6=E4=B8=8E?= =?UTF-8?q?=E4=B8=BB=E7=BA=BF=E7=A8=8B=E6=97=B6=E5=BA=8F=E9=94=99=E4=B9=B1?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E6=89=AB=E6=8F=8F=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/DlgSetting.cpp | 7 +- sane/scanner.cpp | 62 ++++++++----- sane/scanner.h | 1 + twain/twain/huagaods.cpp | 190 +++++++++++++++++++++++++++++++-------- twain/twain/huagaods.hpp | 15 +++- 5 files changed, 214 insertions(+), 61 deletions(-) diff --git a/sane/DlgSetting.cpp b/sane/DlgSetting.cpp index a670633..bd709fc 100644 --- a/sane/DlgSetting.cpp +++ b/sane/DlgSetting.cpp @@ -545,9 +545,12 @@ void dlg_setting::save_changes_to_cur_scheme(int reason) if (changed) { dlg_save_scheme dlg(hwnd()); - + std::wstring sug(L""); + + sug = local_trans::a2u(twain_schm_->auto_gen_scheme_name(local_trans::lang_trans_between_hz936, nullptr, false).c_str(), CP_UTF8); dlg.set_info(local_trans::a2u(twain_schm_->get_scheme_name().c_str(), CP_UTF8).c_str(), now - , SAVE_METHOD_MASK(SAVE_DISCARD) | SAVE_METHOD_MASK(SAVE_NEW)); + , SAVE_METHOD_MASK(SAVE_DISCARD) | SAVE_METHOD_MASK(SAVE_NEW), + sug.c_str()); dlg.do_modal(hwnd()); if(dlg.get_dispose() == SAVE_NEW) { diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 208ae8c..e7ebfff 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -333,7 +333,7 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS , dpi_(200), tmp_path_(L""), img_ind_(0) , scanner_name_(L""), cfg_(NULL), is_ui_wait_img_(false), is_scanning_(false) , scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL), user_cancel_(false) - , max_img_mem_(1 * 1024), twain_set_(false) + , max_img_mem_(1 * 1024), twain_set_(false), ev_cnt_(0) { cfg_ = new gb::scanner_cfg(); cfg_->set_language_transform(&callback::language_trans, NULL); @@ -624,41 +624,41 @@ void scanner::on_ui_event(int uev, void* sender) if (indicator) indicator_.reset(); + is_scanning_ = false; if (err_ && setting_.get()) { return; } - is_scanning_ = false; } - int(__stdcall * h)(int, void*) = scanner_ev_handler_; - if (h) - { - if (SANE_EVENT_UI_CLOSE_SETTING == uev) - { - is_scanning_ = false; - setting_.reset(); - } + //int(__stdcall * h)(int, void*) = scanner_ev_handler_; + //if (h) + //{ + // if (SANE_EVENT_UI_CLOSE_SETTING == uev) + // { + // is_scanning_ = false; + // setting_.reset(); + // } - h(uev, evh_param_); - return; - } + // h(uev, evh_param_); + // return; + //} - if (prev_start_result_ != SANE_STATUS_GOOD && indicator) - indicator_.reset(); - else + //if (prev_start_result_ != SANE_STATUS_GOOD && indicator) + // indicator_.reset(); + //else { - if (uev == SANE_EVENT_UI_SCAN_COMMAND) - { - ui_show_progress(NULL); - start(); - return; - } + //if (uev == SANE_EVENT_UI_SCAN_COMMAND) + //{ + // ui_show_progress(NULL); + // start(); + // return; + //} if (/*events_.count() > 5 && !is_ui_wait_img_ &&*/ (uev == SANE_EVENT_UI_CLOSE_CANCEL || uev == SANE_EVENT_UI_CLOSE_NORMAL || uev == SANE_EVENT_UI_CLOSE_SETTING)) { - events_.clear(); + // events_.clear(); ui_hide(); if(indicator || !indicator_.get()) uev = SANE_EVENT_SCAN_FINISHED; @@ -667,6 +667,21 @@ void scanner::on_ui_event(int uev, void* sender) } events_.save(uev, sizeof(uev)); + ev_cnt_++; + } + + if (ev_cnt_ == events_.count() && + (ev_cnt_ >= 5 || (ev_cnt_ > 1 && !is_scanning_))) + { + // maybe no event has been handled by APP, triggered by callback + int(__stdcall * h)(int, void*) = scanner_ev_handler_; + if (h) + { + wchar_t info[128] = { 0 }; + swprintf_s(info, _countof(info) - 1, L"[CRAZY]%d scanner events stored but APP has no action, we try to trigger it ONCE ...\r\n", ev_cnt_); + ev_cnt_--; + h(events_.take(), evh_param_); + } } } std::string scanner::choose_scanner(const std::vector& scanners) @@ -2261,6 +2276,7 @@ COM_API_IMPLEMENT(scanner, int, start(void)) { int ret = SANE_STATUS_GOOD; + ev_cnt_ = 0; events_.clear(); images_.clear(); scan_msg_ = "OK"; diff --git a/sane/scanner.h b/sane/scanner.h index 4c83890..f6df115 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -50,6 +50,7 @@ class scanner : public ISaneInvoker, virtual public refer safe_img_queue images_; size_t max_img_mem_; safe_queue events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件 + int ev_cnt_; SANE_FinalImgFormat img_fmt_; std::unique_ptr indicator_; std::unique_ptr setting_; diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index 2e1809e..74ef82b 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -853,7 +853,7 @@ static const SCANNERID scanner_guid = MAKE_SCANNER_ID(PRODUCT_PID, PRODUCT_VID); static std::once_flag oc; -huagao_ds::huagao_ds() : cur_head_(NULL), dpi_(200), log_all_triple_(false) +huagao_ds::huagao_ds() : cur_head_(NULL), dpi_(200), xfer_ready_failed_(false), log_all_triple_(false), scanner_status_(SCANNER_STATUS_NOT_INIT) { //std::call_once(oc, [&]() { log4cplus::Initializer(); }); } @@ -892,7 +892,7 @@ void huagao_ds::showmsg(const char* msg, int err) } int __stdcall huagao_ds::on_scanner_event(int ev, void* param) { - return ((huagao_ds*)param)->handle_scanner_event(ev); + return ((huagao_ds*)param)->handle_scanner_event(ev, false); } const Identity& huagao_ds::defaultIdentity() noexcept { @@ -1056,6 +1056,7 @@ Result huagao_ds::identityOpenDs(const Identity& id) m_compression = Compression::None; init_support_caps(); m_fileXfer.setFormat(ImageFileFormat::Bmp); + scanner_status_ = SCANNER_STATUS_READY; return success(); } @@ -1073,6 +1074,7 @@ Result huagao_ds::identityCloseDs(const Identity&) singleton_ = NULL; } load_sane_util::uninitialize(); + scanner_status_ = SCANNER_STATUS_NOT_INIT; return success(); } @@ -1081,7 +1083,7 @@ Result huagao_ds::pendingXfersGet(const Identity&, PendingXfers& data) if (!scanner_.get()) return seqError(); - data.setCount(scanner_->get_scanned_images(-1)); + data.setCount(get_scanned_image_count(-1)); return success(); } Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data) @@ -1091,7 +1093,7 @@ Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data) Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data) { pending_xfer_.clear(); - data.setCount(scanner_->get_scanned_images(-1)); + data.setCount(get_scanned_image_count(-1)); return success(); } @@ -1101,7 +1103,7 @@ Result huagao_ds::setupMemXferGet(const Identity& id, SetupMemXfer& data) size_t total = 0; DWORD to = cur_head_ ? -1 : 0; - if (!scanner_.get() || scanner_->get_scanned_images(to) == 0) + if (!scanner_.get() || get_scanned_image_count(to) == 0) { if (cur_head_) { @@ -1155,7 +1157,10 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw())) return seqError(); + xfer_ready_failed_ = false; scanner_->twain_set_transfer((twain_xfer)m_capXferMech); + scanner_status_ = SCANNER_STATUS_SCAN_1; + app_trigger_event_ = false; int err = scanner_->start(); if (err == SCANNER_ERR_OK) { @@ -1163,6 +1168,7 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) } else { + scanner_status_ = SCANNER_STATUS_READY; // if (err == SCANNER_ERR_DEVICE_NO_PAPER) return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) }; @@ -1231,7 +1237,7 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) { if (!scanner_->wait_image()) { - notifyCloseOk(); + // notifyCloseOk(); return success(); // ÷Ҫسɹ } ok = scanner_->get_first_image_header(&head, NULL, &res); @@ -1277,8 +1283,10 @@ Result huagao_ds::imageLayoutGet(const Identity&, ImageLayout& data) { SANE_Parameters head = { 0 }; - if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0) + if (!scanner_.get()) return seqError(); + else if(get_scanned_image_count(-1) == 0) + return { ReturnCode::XferDone, ConditionCode::Success }; int res = 200; @@ -1312,13 +1320,15 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data) if (!scanner_.get()) return seqError(); - if (scanner_->get_scanned_images(-1) == 0 && !pending_xfer_.img) + if (get_scanned_image_count(-1) == 0 && !pending_xfer_.img) { - if (!cur_head_ || !scanner_->wait_image()) - { - notifyCloseOk(); - return seqError(); - } + //if (!cur_head_ || !scanner_->wait_image()) + //{ + // notifyCloseOk(); + // return seqError(); + //} + + return { ReturnCode::XferDone, ConditionCode::Success }; } IScanImg *img = pending_xfer_.img ? pending_xfer_.img : scanner_->take_first_image(TWAIN_XFER_Memory); @@ -1391,8 +1401,10 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data) } Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data) { - if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0) + if (!scanner_.get()) return seqError(); + else if(get_scanned_image_count(-1) == 0) + return { ReturnCode::XferDone, ConditionCode::Success }; IScanImg* img = scanner_->take_first_image(TWAIN_XFER_Native); @@ -1430,8 +1442,10 @@ Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXf Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin) { // assume that the file format has set before start-scanning, so we write-down the image content to file directly here ... - if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0) + if (!scanner_.get()) return seqError(); + else if(get_scanned_image_count(-1) == 0) + return { ReturnCode::XferDone, ConditionCode::Success }; IScanImg* img = scanner_->take_first_image(TWAIN_XFER_File); Twpp::Result ret = seqError(); @@ -1596,14 +1610,10 @@ Result huagao_ds::call(const Identity& origin, DataGroup dg, Dat dat, Msg msg, v try { // we can override almost anything from SourceFromThis, even the top-most source instance call //FileTools::write_log("D:\\1.txt", "call:datagroup-"+to_string((int)dg)+"dat-"+to_string(int(dat))+"msg-"+to_string(int(msg))); - if (dat == Dat::ImageNativeXfer && state() == DsState::Enabled) // ľɨ˲״̬ı䣬ֱȡͼ˴һ״̬ 2022-11-07 - { - load_sane_util::log_info(L"APP SEQ ERROR: fetch image while status in 'Enabled' yet! we change it to 'XferReady' manually.\r\n", 0); - - notifyXferReady(); - } - Result rt; + + trigger_ProcessEvent(dg, dat, msg); // some APPs may be not trigger (Control, Event, ProcessEvent), we help them :( ... // ľɨ˲״̬ı䣬ֱȡͼ˴һ״̬ 2022-11-07 + rt = Base::call(origin, dg, dat, msg, data); if(log_all_triple_ || (int)rt.returnCode()) { @@ -3312,9 +3322,11 @@ DWORD huagao_ds::get_config_number(const wchar_t* sec, const wchar_t* key) else return GetPrivateProfileIntW(sec, key, 0, get_config_file().c_str()); } -int huagao_ds::handle_scanner_event(int ev) +int huagao_ds::handle_scanner_event(int ev, bool from_event_proc) { static int count_0 = 0; + ReturnCode rc = ReturnCode::Success; + int ret = 0; if (ev == 0) count_0++; @@ -3322,41 +3334,149 @@ int huagao_ds::handle_scanner_event(int ev) { wchar_t msg[128] = { 0 }; if (count_0) - swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", count_0, ev); + swprintf_s(msg, _countof(msg) - 1, L"[%x]handle_scanner_event(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", GetCurrentThreadId(), count_0, ev); else - swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x%x)\r\n", ev); + swprintf_s(msg, _countof(msg) - 1, L"[%x]handle_scanner_event(0x%x)\r\n", GetCurrentThreadId(), ev); load_sane_util::log_info(msg, 0); count_0 = 0; } switch (ev) { case SANE_EVENT_WORKING: - notifyXferReady(); + scanner_status_ = SCANNER_STATUS_SCANNING; + rc = notifyXferReady(); + if (!Twpp::success(rc)) + { + wchar_t msg[128] = { 0 }; + swprintf_s(msg, _countof(msg) - 1, L"[%x]Warning: change state to XferReady failed with error %d while in state(%d), STOP scanning ...\r\n", GetCurrentThreadId(), rc, state()); + load_sane_util::log_info(msg, 0); + + // we stop scanning here ... + scanner_->stop(); + } break; case SANE_EVENT_UI_CLOSE_CANCEL: scanner_->stop(); - // notifyEndWithoutImages(); - notifyCloseCancel(); // ޸ȿ"ȡ"ťUIBUG - added on 2023-02-14 - break; + //notifyCloseCancel(); // ޸ȿ"ȡ"ťUIBUG - added on 2023-02-14 + //break; case SANE_EVENT_UI_CLOSE_NORMAL: scanner_->ui_hide(); case SANE_EVENT_SCAN_FINISHED: + scanner_status_ = SCANNER_STATUS_STOPPED; //notifyCloseOk(); //break; case SANE_EVENT_UI_CLOSE_SETTING: - if(m_bIndicator) - notifyCloseCancel(); - else - notifyXferReady(); // ÷Ҫ֪ͨ FAINT :( - modified on 2022-10-20 + notifyCloseCancel(); + if (ev == SANE_EVENT_UI_CLOSE_SETTING) + { + rc = notifyXferReady(); // ÷Ҫ֪ͨ FAINT :( - modified on 2022-10-20 + if (!Twpp::success(rc)) + { + wchar_t msg[128] = { 0 }, unk[20] = { 0 }; + swprintf_s(msg, _countof(msg) - 1, L"[%x]yscan: notifyXferReady failed after setting UI closed with error %d\r\n", GetCurrentThreadId(), rc); + load_sane_util::log_info(msg, 0); + } + } break; case SANE_EVENT_UI_SCAN_COMMAND: - scanner_->ui_show_progress(NULL); - scanner_->start(); + if (m_bIndicator) + scanner_->ui_show_progress(NULL); + else + scanner_->ui_hide(); + scanner_status_ = SCANNER_STATUS_SCAN_1; + app_trigger_event_ = false; + if ((ret = scanner_->start())) + { + wchar_t msg[128] = { 0 }, unk[20] = { 0 }; + swprintf_s(msg, _countof(msg) - 1, L"[%x - %s]Fatal: start scanning from setting UI failed with error %d\r\n", GetCurrentThreadId(), desc_state(state(), unk), ret); + load_sane_util::log_info(msg, 0); + + scanner_status_ = SCANNER_STATUS_STOPPED; + rc = notifyCloseCancel(); + if (Twpp::success(rc)) + { + scanner_status_ = SCANNER_STATUS_READY; + } + else + { + swprintf_s(msg, _countof(msg) - 1, L"[%x]Warning: notifyCloseCancel failed with error %d after start scanning failed\r\n", GetCurrentThreadId(), rc, state()); + load_sane_util::log_info(msg, 0); + } + } break; } return 0; } +int huagao_ds::get_scanned_image_count(DWORD timeout) +{ + int cnt = scanner_->get_scanned_images(timeout); + //if (cnt == -1) + //{ + // // This is a special value indicates the scanning is over + // cnt = 0; + // scanner_->ui_hide(); + // notifyCloseCancel(); + //} + return cnt; +} +void huagao_ds::trigger_ProcessEvent(Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg) +{ + ReturnCode rc; + + if (state() == DsState::Enabled && scanner_status_ >= SCANNER_STATUS_SCAN_1) // in scanning events ... + { + // here ensure APP enter into XferImage process ... + if (!app_trigger_event_ && scanner_status_ == SCANNER_STATUS_STOPPED) + { + // scanning stopped, reset APP state to ready ... + scanner_status_ = SCANNER_STATUS_READY; + rc = notifyCloseCancel(); + if (!Twpp::success(rc)) + { + wchar_t info[128] = { 0 }, unk[20] = { 0 }; + swprintf_s(info, _countof(info) - 1, L"[%x]Warning: notifyCloseCancel failed with error %s!\r\n", GetCurrentThreadId(), desc_return_code(rc, unk)); + load_sane_util::log_info(info, 0); + } + } + else + { + // start scanning, expect frist TRIPLE is ProcessEvent ... + if (dg == DataGroup::Control && dat == Dat::Event && msg == Msg::ProcessEvent && scanner_status_ == SCANNER_STATUS_SCAN_1) + { + app_trigger_event_ = true; // nothing else to do + load_sane_util::log_info(L"Good! first event is (Control, Event, ProcessEvent) after start scanning ^_^.\r\n", 0); + } + else if(!app_trigger_event_) + { + int ev = 0; + + if (scanner_status_ == SCANNER_STATUS_SCAN_1) + load_sane_util::log_info(L"Sorry, first event is not (Control, Event, ProcessEvent) after start scanning, we takeover it!\r\n", 0); + if (scanner_.get()) + { + ev = scanner_->get_event(); + if (ev) + handle_scanner_event(ev, true); + } + } + } + } + else if (state() >= DsState::XferReady && scanner_status_ == SCANNER_STATUS_STOPPED) + { + // here ensure APP return to ready state ... + if (scanner_.get() && scanner_->get_scanned_images(0) == 0) + { + rc = notifyCloseCancel(); + if (!Twpp::success(rc)) + { + wchar_t info[128] = { 0 }, unk[20] = { 0 }; + swprintf_s(info, _countof(info) - 1, L"[%x]Warning: notifyCloseCancel failed with error %s when scanner is stopped!\r\n", GetCurrentThreadId(), desc_return_code(rc, unk)); + load_sane_util::log_info(info, 0); + } + } + } +} diff --git a/twain/twain/huagaods.hpp b/twain/twain/huagaods.hpp index 1b3000f..f1b9b98 100644 --- a/twain/twain/huagaods.hpp +++ b/twain/twain/huagaods.hpp @@ -23,6 +23,14 @@ namespace std { class twain_ui; +enum scanner_status +{ + SCANNER_STATUS_NOT_INIT = 0, // has not call identityOpenDs or called identityCloseDs + SCANNER_STATUS_READY, // called identityOpenDs + SCANNER_STATUS_SCAN_1, // scanner_->start() should be called + SCANNER_STATUS_SCANNING, // received SANE_EVENT_WORKING + SCANNER_STATUS_STOPPED, // received SANE_EVENT_SCAN_FINISHED +}; class huagao_ds : public Twpp::SourceFromThis { std::unordered_map> m_caps; std::unordered_map m_query; @@ -42,7 +50,10 @@ class huagao_ds : public Twpp::SourceFromThis { Twpp::Compression m_compression = Twpp::Compression::None; SANE_Parameters* cur_head_; int dpi_; + int scanner_status_; + bool xfer_ready_failed_; bool log_all_triple_; + bool app_trigger_event_; static std::string get_hidedlg_path(void); static void showmsg(const char* msg, int err); @@ -56,7 +67,9 @@ class huagao_ds : public Twpp::SourceFromThis { std::wstring get_config_file(void); std::wstring get_config_value(const wchar_t* sec, const wchar_t* key); DWORD get_config_number(const wchar_t* sec, const wchar_t* key); - int handle_scanner_event(int ev); + int handle_scanner_event(int ev, bool from_event_proc = true); + int get_scanned_image_count(DWORD timeout); + void trigger_ProcessEvent(Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg); typedef struct _pending_xfer {