Improve the scanning and image saving process

This commit is contained in:
gb 2023-04-08 10:49:19 +08:00
parent 1df41ab602
commit 4d65a65568
6 changed files with 156 additions and 13 deletions

View File

@ -1465,22 +1465,27 @@ public:
void dump_buf(uint8_t *data, int len)
{
uint32_t addr = 0;
std::string asc("");
std::string cont(""), asc("");
char buf[20] = { 0 };
for(int i = 0; i < len; ++i)
{
if((i % 16) == 0)
{
printf(" %s\n0x%08x ", asc.c_str(), addr);
if (cont.length())
log_cls::log(LOG_LEVEL_ALL, "%s %s\n", cont.c_str(), asc.c_str());
sprintf(buf, "0x%08x ", addr);
addr += 16;
cont = buf;
asc = "";
}
else if((i % 8) == 0)
{
printf(" ");
cont += " ";
}
uint8_t v = data[i];
printf("%02X ", v);
sprintf(buf, "%02X ", v);
cont += buf;
if(v >= 0x20 && v < 0x7f)
asc.append(1, v);
else
@ -1495,10 +1500,8 @@ void dump_buf(uint8_t *data, int len)
pad.erase((16 - asc.length()) * 3);
else
pad = "";
printf("%s %s", pad.c_str(), asc.c_str());
log_cls::log(LOG_LEVEL_ALL, "%s%s %s\n", cont.c_str(), pad.c_str(), asc.c_str());
}
printf("\n");
}
dyn_mem_ptr UsbDevice::unhandled_ep0(struct usb_functionfs_event* pev)
@ -1659,6 +1662,14 @@ dyn_mem_ptr UsbDevice::handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_
*required = dynamic_cast<packet_data_base_ptr>(reader);
}
break;
default:
log_cls::log(LOG_LEVEL_ALL, "Unhandled Packet with command %d:\n", pack->cmd);
dump_buf((uint8_t*)pack, *used);
reply = dyn_mem::memory(base_head_size);
LPPACK_BASE p = (LPPACK_BASE)reply->ptr();
BASE_PACKET_REPLY(*p, pack->cmd + 1, pack->pack_id, EINVAL);
reply->set_len(base_head_size);
break;
}
return reply;

View File

@ -573,7 +573,7 @@ IMPLEMENT_DYNAMIC(CDlgScanner, CDialogEx)
CDlgScanner::CDlgScanner(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_SCANNER, pParent)
, scanner_(NULL), auto_tx_file_(-1), auto_tx_(false)
, setting_ui_(NULL)
, setting_ui_(NULL), img_cnt_(0)
{
g_my_inst = GetModuleHandle(NULL);
@ -627,6 +627,47 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
setting_ui_ = NULL;
}
auto progresser = [&](uint64_t total, uint64_t cur, uint32_t err) -> int
{
if (err)
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str());
else if (cur >= total)
SetDlgItemInt(IDC_EDIT_COUNT, img_cnt_);
return 0;
};
auto img_keeper = [&](LPPACKIMAGE img, uint64_t size) -> data_holder_ptr
{
if (img)
{
file_saver* saver = new file_saver();
std::string root(usb::u2a(img_root_.c_str()));
char name[40] = { 0 };
sprintf_s(name, _countof(name) - 1, "scan_%03x.jpg", ++img_cnt_);
if (saver->open((root + name).c_str(), size))
{
saver->release();
saver = NULL;
}
else
saver->set_progress_notify(progresser);
return dynamic_cast<data_holder_ptr>(saver);
}
else
{
// scan stopped ...
::SetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, L"Scan");
if (size)
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Error: " + std::to_wstring(size) + L")").c_str());
else
::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L" (Good)").c_str());
return NULL;
}
};
if (pnp)
{
int err = 0;
@ -638,6 +679,7 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
scanner_->release();
scanner_ = NULL;
msg_box(m_hWnd, MB_OK, L"Error", L"Open %04X:%04X failed with error %d.", pnp->vid, pnp->pid, err);
enable_buttons(false);
}
else
{
@ -651,9 +693,14 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp)
if (err)
{
msg_box(m_hWnd, MB_OK, L"Unsupported Scanner", L"Failed to get protocol version with error %d.", err);
scanner_->release();
scanner_ = NULL;
enable_buttons(false);
}
else
{
scanner_->set_image_receiver(img_keeper);
swprintf_s(buf, _countof(buf) - 1, L"%u.%u", h, l);
SetDlgItemTextW(IDC_EDIT_PROTOCOL_VER, buf);
@ -870,6 +917,26 @@ BOOL CDlgScanner::OnInitDialog()
sane_api_.sane_init_api = &sane::sane_init_api;
sane_api_.sane_exit_api = &sane::sane_exit_api;
wchar_t path[MAX_PATH] = { 0 };
std::wstring root(L"");
GetModuleFileNameW(NULL, path, _countof(path) - 1);
wcsrchr(path, L'\\')[1] = 0;
root = path;
if (GetPrivateProfileStringW(L"config", L"img-path", L"", path, _countof(path) - 1, (root + L"config.txt").c_str()))
{
img_root_ = path;
}
else
{
img_root_ = root + L"imgs";
}
STR_SIMPLIFY_PATH(img_root_);
file_util::force_create_folder(img_root_.c_str(), NULL, false);
if(img_root_[img_root_.length() - 1] != L'\\')
img_root_ += L"\\";
::SetDlgItemTextW(m_hWnd, IDC_EDIT_IMG_PATH, img_root_.c_str());
return FALSE; // 除非将焦点设置到控件,否则返回 TRUE
}
BOOL CDlgScanner::PreTranslateMessage(MSG* pMsg)
@ -944,10 +1011,61 @@ void CDlgScanner::OnBnClickedButtonResetBulk()
void CDlgScanner::OnBnClickedButtonBrowseSavingPath()
{
// TODO: 在此添加控件通知处理程序代码
LPITEMIDLIST pidRoot = NULL;
BROWSEINFOW bi = { 0 };
wchar_t path[MAX_PATH] = { 0 };
SHGetSpecialFolderLocation(m_hWnd, CSIDL_DRIVES, &pidRoot);
bi.hwndOwner = m_hWnd;
bi.pidlRoot = pidRoot;
bi.lpszTitle = L"Select folder to save scanning images";
bi.pszDisplayName = path;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
pidRoot = SHBrowseForFolderW(&bi);
if (pidRoot)
{
SHGetPathFromIDListW(pidRoot, path);
img_root_ = path;
img_root_ += L"\\";
STR_SIMPLIFY_PATH(img_root_);
::SetDlgItemTextW(m_hWnd, IDC_EDIT_IMG_PATH, img_root_.c_str());
std::wstring root(L"");
GetModuleFileNameW(NULL, path, _countof(path) - 1);
wcsrchr(path, L'\\')[1] = 0;
root = path;
WritePrivateProfileStringW(L"config", L"img-path", img_root_.c_str(), (root + L"config.txt").c_str());
}
}
void CDlgScanner::OnBnClickedButtonScan()
{
// TODO: 在此添加控件通知处理程序代码
wchar_t title[40] = { 0 };
::GetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, title, _countof(title) - 1);
if (wcsicmp(title, L"Scan") == 0)
{
img_cnt_ = 0;
SetDlgItemInt(IDC_EDIT_COUNT, img_cnt_);
if (scanner_)
{
int err = scanner_->scan_start();
if (err)
msg_box(m_hWnd, MB_OK, L"Error", L"Failed in startin scanning with code %d", err);
else
::SetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, L"Stop");
}
}
else
{
if (scanner_)
{
int err = scanner_->scan_stop();
if (err)
msg_box(m_hWnd, MB_OK, L"Error", L"Failed to stop scanning with code %d", err);
}
}
}
void CDlgScanner::OnBnClickedButtonBrowseFile()
{

View File

@ -57,6 +57,8 @@ class CDlgScanner : public CDialogEx
HANDLE auto_wait_;
dlg_setting *setting_ui_;
SANEAPI sane_api_;
std::wstring img_root_;
uint32_t img_cnt_;
public:
CDlgScanner(CWnd* pParent = nullptr); // 标准构造函数

View File

@ -133,7 +133,7 @@ int cmd_result::clean(void)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// scanner_handler
scanner_handler::scanner_handler(void) : usb_(nullptr), status_(SCANNER_STATUS_NOT_OPEN)
scanner_handler::scanner_handler(void) : usb_(nullptr), status_(SCANNER_STATUS_NOT_OPEN), img_receiver_(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)>())
{
auto on_reply = [&](dyn_mem_ptr reply, uint32_t* used, packet_data_base_ptr* more) ->dyn_mem_ptr
{
@ -186,6 +186,15 @@ scanner_handler::scanner_handler(void) : usb_(nullptr), status_(SCANNER_STATUS_N
*more = dynamic_cast<packet_data_base_ptr>(receiver);
}
}
else if (pack->cmd == PACK_CMD_SCAN_STOP_ROGER)
{
data_holder_ptr receiver = img_receiver_(NULL, pack->data);
if (receiver)
receiver->release();
*used = sizeof(PACK_BASE);
status_ = pack->data;
}
else if (pack->cmd == PACK_CMD_STATUS_ROGER)
{
*used = sizeof(PACK_BASE);
@ -543,10 +552,12 @@ int scanner_handler::status_get(void)
return status_;
}
int scanner_handler::scan_start(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)> img)
void scanner_handler::set_image_receiver(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)> img)
{
img_receiver_ = img;
}
int scanner_handler::scan_start(void)
{
auto call = [&](cmd_result* cmd) -> int
{
return usb_->scan_start(cmd->get_id());

View File

@ -110,7 +110,8 @@ public:
int option_value_set(const char* name, uint32_t type, void* buf, uint32_t size/*buffer size of 'buf'*/, uint8_t* after);
int status_get(void);
int scan_start(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)> img);
void set_image_receiver(std::function<data_holder_ptr(LPPACKIMAGE/*NULL when scanning stopped*/, uint64_t/*size in image, error in stopped*/)> img);
int scan_start(void);
int scan_stop(void);
int file_transfer(const char* local_path, const char* remote_path, bool to_device