回调方式取图
This commit is contained in:
parent
712d49809b
commit
79f8208ea4
|
@ -254,13 +254,14 @@ __declspec(novtable) struct ISaneInvoker : public IRef
|
||||||
SANE_OPTION_ID_API_EX(ip); // std::string
|
SANE_OPTION_ID_API_EX(ip); // std::string
|
||||||
|
|
||||||
// ui ...
|
// ui ...
|
||||||
COM_API_DECLARE(void, ui_show_main(void));
|
COM_API_DECLARE(bool, ui_show_main(HWND parent));
|
||||||
COM_API_DECLARE(void, ui_show_setting(bool with_scan));
|
COM_API_DECLARE(bool, ui_show_setting(HWND parent, bool with_scan));
|
||||||
COM_API_DECLARE(void, ui_show_progress(void));
|
COM_API_DECLARE(bool, ui_show_progress(HWND parent));
|
||||||
COM_API_DECLARE(void, ui_hide(void));
|
COM_API_DECLARE(void, ui_hide(void));
|
||||||
COM_API_DECLARE(void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len));
|
|
||||||
COM_API_DECLARE(bool, ui_is_ok(void));
|
COM_API_DECLARE(bool, ui_is_ok(void));
|
||||||
COM_API_DECLARE(bool, ui_is_progress_ui_showing(void));
|
|
||||||
|
// twain
|
||||||
|
COM_API_DECLARE(void, twain_set_transfer(twain_xfer xfer));
|
||||||
};
|
};
|
||||||
|
|
||||||
struct delete_scanner
|
struct delete_scanner
|
||||||
|
|
|
@ -246,20 +246,20 @@ unsigned char* mapping_buf::buffer(unsigned long long off, unsigned int* bytes)
|
||||||
bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
|
bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
|
||||||
{
|
{
|
||||||
unsigned int len = *bytes, total = 0;
|
unsigned int len = *bytes, total = 0;
|
||||||
unsigned char* buf = buffer(off, &len);
|
unsigned char* buf = buffer(off, &len);
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
const char* src = (const char*)data;
|
const char* src = (const char*)data;
|
||||||
|
|
||||||
while (buf)
|
while (buf)
|
||||||
{
|
{
|
||||||
if (len > *bytes - total)
|
if (len >= *bytes - total)
|
||||||
{
|
{
|
||||||
memcpy(buf, src, *bytes - total);
|
memcpy(buf, src, *bytes - total);
|
||||||
total = *bytes;
|
total = *bytes;
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(buf, data, len);
|
memcpy(buf, src, len);
|
||||||
total += len;
|
total += len;
|
||||||
off += len;
|
off += len;
|
||||||
src += len;
|
src += len;
|
||||||
|
@ -398,50 +398,48 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
|
||||||
ok = total + h.length() + dif == data_->bytes();
|
ok = total + h.length() + dif == data_->bytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
do_result(ok, xfer);
|
||||||
if (ok)
|
}
|
||||||
{
|
scanned_img::scanned_img(SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
|
||||||
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP && channel() == 3 &&
|
, twain_xfer xfer, SANE_FinalImgFormat* fmt) : head_(head), dpi_(dpi), header_size_(0)
|
||||||
xfer != TWAIN_XFER_Memory)
|
{
|
||||||
{
|
if (fmt)
|
||||||
// swap RGB
|
fmt_ = *fmt;
|
||||||
unsigned long long off = 0;
|
|
||||||
unsigned int line = line_bytes(), len = line;
|
|
||||||
for (int i = 0; i < height(); ++i)
|
|
||||||
{
|
|
||||||
int l = head_.bytes_per_line, cur = 0;
|
|
||||||
|
|
||||||
off = i * line + h.length();
|
|
||||||
while (l > 0)
|
|
||||||
{
|
|
||||||
len = l;
|
|
||||||
dst = data_->buffer(off + cur, &len);
|
|
||||||
if (!dst)
|
|
||||||
break;
|
|
||||||
if (len > l)
|
|
||||||
len = l;
|
|
||||||
len /= 3;
|
|
||||||
for (int pos = 0; pos < len; ++pos)
|
|
||||||
{
|
|
||||||
unsigned char uc = dst[pos * 3 + 0];
|
|
||||||
dst[pos * 3 + 0] = dst[pos * 3 + 2];
|
|
||||||
dst[pos * 3 + 2] = uc;
|
|
||||||
}
|
|
||||||
l -= len * 3;
|
|
||||||
cur += len * 3;
|
|
||||||
}
|
|
||||||
if (!dst)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data_->unmap();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete data_;
|
fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
||||||
data_ = NULL;
|
fmt_.detail = 0;
|
||||||
header_size_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t bytes = line_bytes() * head.lines;
|
||||||
|
std::string h(file_header(fmt_.img_format, dpi, xfer));
|
||||||
|
unsigned char* dst = NULL, *src = (unsigned char*)data;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
header_size_ = h.length();
|
||||||
|
data_ = new mapping_buf();
|
||||||
|
bytes += header_size_;
|
||||||
|
dst = data_->allocate(tmp_file, bytes);
|
||||||
|
bytes = h.length();
|
||||||
|
if (dst && data_->save(h.c_str(), &bytes, 0))
|
||||||
|
{
|
||||||
|
unsigned long long off = bytes, line_l = line_bytes();
|
||||||
|
unsigned int buf_len = line_bytes(), row = 0;
|
||||||
|
if (xfer == TWAIN_XFER_Memory)
|
||||||
|
line_l *= -1;
|
||||||
|
else
|
||||||
|
off = data_->bytes() - line_l;
|
||||||
|
for (; row < head.lines; ++row)
|
||||||
|
{
|
||||||
|
bytes = head.bytes_per_line;
|
||||||
|
if (!data_->save(src, &bytes, off))
|
||||||
|
break;
|
||||||
|
off -= line_l;
|
||||||
|
src += head.bytes_per_line;
|
||||||
|
}
|
||||||
|
ok = row == head.lines;
|
||||||
|
}
|
||||||
|
do_result(ok, xfer);
|
||||||
}
|
}
|
||||||
scanned_img::~scanned_img()
|
scanned_img::~scanned_img()
|
||||||
{
|
{
|
||||||
|
@ -481,6 +479,59 @@ std::string scanned_img::file_header(SANE_ImageType type, float resolution, twai
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
void scanned_img::do_result(bool ok, twain_xfer xfer)
|
||||||
|
{
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP
|
||||||
|
&& channel() == 3
|
||||||
|
&& xfer != TWAIN_XFER_Memory)
|
||||||
|
{
|
||||||
|
// swap RGB
|
||||||
|
swap_rgb();
|
||||||
|
}
|
||||||
|
data_->unmap();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete data_;
|
||||||
|
data_ = NULL;
|
||||||
|
header_size_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void scanned_img::swap_rgb(void)
|
||||||
|
{
|
||||||
|
unsigned long long off = 0;
|
||||||
|
unsigned int line = line_bytes(), len = line;
|
||||||
|
unsigned char* dst = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < height(); ++i)
|
||||||
|
{
|
||||||
|
int l = head_.bytes_per_line, cur = 0;
|
||||||
|
|
||||||
|
off = i * line + header_size_;
|
||||||
|
while (l > 0)
|
||||||
|
{
|
||||||
|
len = l;
|
||||||
|
dst = data_->buffer(off + cur, &len);
|
||||||
|
if (!dst)
|
||||||
|
break;
|
||||||
|
if (len > l)
|
||||||
|
len = l;
|
||||||
|
len /= 3;
|
||||||
|
for (int pos = 0; pos < len; ++pos)
|
||||||
|
{
|
||||||
|
unsigned char uc = dst[pos * 3 + 0];
|
||||||
|
dst[pos * 3 + 0] = dst[pos * 3 + 2];
|
||||||
|
dst[pos * 3 + 2] = uc;
|
||||||
|
}
|
||||||
|
l -= len * 3;
|
||||||
|
cur += len * 3;
|
||||||
|
}
|
||||||
|
if (!dst)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IRef
|
// IRef
|
||||||
COM_API_IMPLEMENT(scanned_img, long, add_ref(void))
|
COM_API_IMPLEMENT(scanned_img, long, add_ref(void))
|
||||||
|
@ -557,3 +608,70 @@ COM_API_IMPLEMENT(scanned_img, void, copy_header(SANE_Parameters* head))
|
||||||
{
|
{
|
||||||
*head = head_;
|
*head = head_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class safe_img_queue
|
||||||
|
safe_img_queue::safe_img_queue()
|
||||||
|
{}
|
||||||
|
safe_img_queue::~safe_img_queue()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t safe_img_queue::count(void)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(que_lock_);
|
||||||
|
|
||||||
|
return queue_.size();
|
||||||
|
}
|
||||||
|
bool safe_img_queue::save(scanned_img* img)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(que_lock_);
|
||||||
|
|
||||||
|
queue_.push_back(img);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool safe_img_queue::get_header(SANE_Parameters* header)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(que_lock_);
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if (queue_.size())
|
||||||
|
{
|
||||||
|
queue_[0]->copy_header(header);
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
scanned_img* safe_img_queue::take(void)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(que_lock_);
|
||||||
|
scanned_img* img = NULL;
|
||||||
|
|
||||||
|
if (queue_.size())
|
||||||
|
{
|
||||||
|
img = queue_[0];
|
||||||
|
queue_.erase(queue_.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
void safe_img_queue::clear()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(que_lock_);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < queue_.size(); ++i)
|
||||||
|
queue_[i]->release();
|
||||||
|
queue_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "s2t_api.h"
|
#include "s2t_api.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class refer : public IRef
|
class refer : public IRef
|
||||||
{
|
{
|
||||||
|
@ -59,10 +60,14 @@ class scanned_img : public IScanImg, virtual public refer
|
||||||
SANE_FinalImgFormat fmt_;
|
SANE_FinalImgFormat fmt_;
|
||||||
|
|
||||||
std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer);
|
std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer);
|
||||||
|
void do_result(bool ok, twain_xfer xfer);
|
||||||
|
void swap_rgb(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file
|
scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file
|
||||||
, twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
|
, twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
|
||||||
|
scanned_img(SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
|
||||||
|
, twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -90,6 +95,23 @@ public:
|
||||||
COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));
|
COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class safe_img_queue
|
||||||
|
{
|
||||||
|
std::mutex que_lock_;
|
||||||
|
std::vector<scanned_img*> queue_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
safe_img_queue();
|
||||||
|
~safe_img_queue();
|
||||||
|
|
||||||
|
public:
|
||||||
|
size_t count(void);
|
||||||
|
bool save(scanned_img* img);
|
||||||
|
bool get_header(SANE_Parameters* header);
|
||||||
|
scanned_img* take(void);
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
namespace local_trans
|
namespace local_trans
|
||||||
{
|
{
|
||||||
std::string u2a(const wchar_t* unic, UINT cp = CP_ACP);
|
std::string u2a(const wchar_t* unic, UINT cp = CP_ACP);
|
||||||
|
|
170
sane/scanner.cpp
170
sane/scanner.cpp
|
@ -6,6 +6,7 @@
|
||||||
#include "../../code_device/hgsane/sane_hg_mdw.h"
|
#include "../../code_device/hgsane/sane_hg_mdw.h"
|
||||||
#include "sane_option_trans.h"
|
#include "sane_option_trans.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
|
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
|
||||||
|
@ -18,10 +19,74 @@ static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// callback
|
||||||
|
namespace callback
|
||||||
|
{
|
||||||
|
static std::mutex cb_lock_;
|
||||||
|
typedef struct _scanner_inst
|
||||||
|
{
|
||||||
|
SANE_Handle dev;
|
||||||
|
scanner* invoker;
|
||||||
|
|
||||||
|
bool operator==(const SANE_Handle& h)
|
||||||
|
{
|
||||||
|
return dev == h;
|
||||||
|
}
|
||||||
|
bool operator==(const scanner* obj)
|
||||||
|
{
|
||||||
|
return invoker == obj;
|
||||||
|
}
|
||||||
|
}SCNINST;
|
||||||
|
std::vector<SCNINST> g_scanner_instances;
|
||||||
|
|
||||||
|
int sane_event_callback( // 注册回调的对象,需要保证该回调是多线程安全的
|
||||||
|
SANE_Handle hdev // 产生事件的设备句柄
|
||||||
|
, int code // 回调事件代码
|
||||||
|
, void* data // 回调事件数据,根据事件代码有所不同,参照具体事件定义
|
||||||
|
, unsigned int* len // 数据长度(字节),或者event_data的缓冲区长度,详细请看相应的事件代码
|
||||||
|
, void* param // 用户自定义数据,与调用sane_init_ex传入时的保持一致
|
||||||
|
) // 返回值依不同的事件代码而定,通常为“0”
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
||||||
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), hdev);
|
||||||
|
|
||||||
|
if (it != g_scanner_instances.end())
|
||||||
|
return it->invoker->handle_event(code, data, len);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void reg_callback(SANE_Handle dev, scanner* invoker)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
||||||
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), dev);
|
||||||
|
if (it == g_scanner_instances.end())
|
||||||
|
{
|
||||||
|
SCNINST inst;
|
||||||
|
|
||||||
|
inst.dev = dev;
|
||||||
|
inst.invoker = invoker;
|
||||||
|
g_scanner_instances.push_back(inst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it->invoker = invoker;
|
||||||
|
}
|
||||||
|
void unreg_callback(scanner* invoker)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(cb_lock_);
|
||||||
|
std::vector<SCNINST>::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), invoker);
|
||||||
|
if (it != g_scanner_instances.end())
|
||||||
|
g_scanner_instances.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// class scanner
|
// class scanner
|
||||||
scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
|
scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
|
||||||
, dpi_(200), tmp_path_(L""), img_ind_(0)
|
, dpi_(200), tmp_path_(L""), img_ind_(0), cb_invoker_(NULL), cb_param_(NULL), working_(false)
|
||||||
{
|
{
|
||||||
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
|
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
|
||||||
tmp_path_ += L"imgs";
|
tmp_path_ += L"imgs";
|
||||||
|
@ -31,7 +96,9 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS
|
||||||
err_ = open();
|
err_ = open();
|
||||||
}
|
}
|
||||||
scanner::~scanner()
|
scanner::~scanner()
|
||||||
{}
|
{
|
||||||
|
callback::unreg_callback(this);
|
||||||
|
}
|
||||||
|
|
||||||
std::string scanner::get_scanner_name(SCANNERID id)
|
std::string scanner::get_scanner_name(SCANNERID id)
|
||||||
{
|
{
|
||||||
|
@ -113,6 +180,7 @@ int scanner::open(void)
|
||||||
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
|
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
|
||||||
if (ret == SANE_STATUS_GOOD)
|
if (ret == SANE_STATUS_GOOD)
|
||||||
{
|
{
|
||||||
|
callback::reg_callback(handle_, this);
|
||||||
ret = init_options_id();
|
ret = init_options_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1372,6 +1440,7 @@ COM_API_IMPLEMENT(scanner, int, start(void))
|
||||||
unsigned int l = sizeof(img_fmt_);
|
unsigned int l = sizeof(img_fmt_);
|
||||||
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l))
|
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l))
|
||||||
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
||||||
|
working_ = true;
|
||||||
}
|
}
|
||||||
prev_start_result_ = ret;
|
prev_start_result_ = ret;
|
||||||
|
|
||||||
|
@ -1379,10 +1448,13 @@ COM_API_IMPLEMENT(scanner, int, start(void))
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, int, stop(void))
|
COM_API_IMPLEMENT(scanner, int, stop(void))
|
||||||
{
|
{
|
||||||
|
working_ = false;
|
||||||
return hg_sane_middleware::instance()->stop(handle_);
|
return hg_sane_middleware::instance()->stop(handle_);
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param))
|
COM_API_IMPLEMENT(scanner, void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param))
|
||||||
{
|
{
|
||||||
|
cb_invoker_ = cb;
|
||||||
|
cb_param_ = param;
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
|
COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
|
||||||
{
|
{
|
||||||
|
@ -1392,24 +1464,18 @@ COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
|
COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
|
||||||
{
|
{
|
||||||
unsigned int count = 0;
|
size_t count = images_.count();
|
||||||
|
|
||||||
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_IMAGE_QUEUE_COUNT, NULL, &count);
|
while (count == 0 && milliseconds && working_)
|
||||||
if (count == 0 && milliseconds)
|
|
||||||
{
|
{
|
||||||
while (count == 0)
|
Sleep(10);
|
||||||
|
count = images_.count();
|
||||||
|
if (milliseconds != -1)
|
||||||
{
|
{
|
||||||
Sleep(10);
|
if (milliseconds <= 10)
|
||||||
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_IMAGE_QUEUE_COUNT, NULL, &count)
|
|
||||||
!= SCANNER_ERR_OK)
|
|
||||||
break;
|
break;
|
||||||
if (milliseconds != -1)
|
|
||||||
{
|
|
||||||
if (milliseconds <= 10)
|
|
||||||
break;
|
|
||||||
|
|
||||||
milliseconds -= 10;
|
milliseconds -= 10;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,22 +1483,13 @@ COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
|
COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
|
||||||
{
|
{
|
||||||
scanned_img* img = NULL;
|
scanned_img* img = images_.take();
|
||||||
SANE_Parameters head;
|
|
||||||
|
|
||||||
if (hg_sane_middleware::instance()->get_image_parameters(handle_, &head) == SANE_STATUS_GOOD)
|
|
||||||
{
|
|
||||||
wchar_t name[40] = { 0 };
|
|
||||||
|
|
||||||
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
|
|
||||||
img = new scanned_img(head, handle_, dpi_, (tmp_path_ + name).c_str(), xfer, &img_fmt_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dynamic_cast<IScanImg*>(img);
|
return dynamic_cast<IScanImg*>(img);
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header))
|
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header))
|
||||||
{
|
{
|
||||||
return hg_sane_middleware::instance()->get_image_parameters(handle_, header) == SANE_STATUS_GOOD;
|
return images_.get_header(header);
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, bool, is_online(void))
|
COM_API_IMPLEMENT(scanner, bool, is_online(void))
|
||||||
{
|
{
|
||||||
|
@ -1712,29 +1769,62 @@ SANE_OPTION_ID_IMPLEMENT(ex_power)
|
||||||
SANE_OPTION_ID_IMPLEMENT(ex_hardware_version)
|
SANE_OPTION_ID_IMPLEMENT(ex_hardware_version)
|
||||||
SANE_OPTION_ID_IMPLEMENT(ex_ip)
|
SANE_OPTION_ID_IMPLEMENT(ex_ip)
|
||||||
|
|
||||||
|
COM_API_IMPLEMENT(scanner, void, twain_set_transfer(twain_xfer xfer))
|
||||||
|
{
|
||||||
|
xfer_ = xfer;
|
||||||
|
}
|
||||||
|
|
||||||
// ui ...
|
// ui ...
|
||||||
COM_API_IMPLEMENT(scanner, void, ui_show_main(void))
|
COM_API_IMPLEMENT(scanner, bool, ui_show_main(HWND parent))
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, void, ui_show_setting(bool with_scan))
|
COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan))
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, void, ui_show_progress(void))
|
COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent))
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, void, ui_hide(void))
|
COM_API_IMPLEMENT(scanner, void, ui_hide(void))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void))
|
COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void))
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
COM_API_IMPLEMENT(scanner, bool, ui_is_progress_ui_showing(void))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int scanner::handle_event(int ev_code, void* data, unsigned int* len)
|
||||||
{
|
{
|
||||||
return false;
|
if (ev_code == SANE_EVENT_IMAGE_OK)
|
||||||
|
{
|
||||||
|
SANE_Image* simg = (SANE_Image*)data;
|
||||||
|
scanned_img* img = NULL;
|
||||||
|
wchar_t name[40] = { 0 };
|
||||||
|
|
||||||
|
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
|
||||||
|
img = new scanned_img(simg->header, simg->data, simg->bytes, dpi_, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
|
||||||
|
if (img->bytes() >= simg->bytes)
|
||||||
|
{
|
||||||
|
images_.save(img);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ev_code == SANE_EVENT_SCAN_FINISHED)
|
||||||
|
{
|
||||||
|
working_ = false;
|
||||||
|
//if (cb_invoker_) // calling this when UI exited
|
||||||
|
// cb_invoker_(ev_code, data, len, cb_param_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1744,6 +1834,14 @@ COM_API_IMPLEMENT(scanner, bool, ui_is_progress_ui_showing(void))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// exports
|
// exports
|
||||||
#ifdef EXPORT_SANE_API
|
#ifdef EXPORT_SANE_API
|
||||||
|
@ -1753,6 +1851,7 @@ __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
int __stdcall initialize(void* reserve)
|
int __stdcall initialize(void* reserve)
|
||||||
{
|
{
|
||||||
|
hg_sane_middleware::set_callback(callback::sane_event_callback, NULL);
|
||||||
hg_sane_middleware::instance();
|
hg_sane_middleware::instance();
|
||||||
|
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
@ -1791,6 +1890,7 @@ __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
int __stdcall uninitialize(void* reserve)
|
int __stdcall uninitialize(void* reserve)
|
||||||
{
|
{
|
||||||
|
hg_sane_middleware::set_callback(NULL, NULL);
|
||||||
hg_sane_middleware::clear();
|
hg_sane_middleware::clear();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -26,11 +26,16 @@ class scanner : public ISaneInvoker, virtual public refer
|
||||||
SANE_Handle handle_;
|
SANE_Handle handle_;
|
||||||
SCANNERID id_;
|
SCANNERID id_;
|
||||||
int err_;
|
int err_;
|
||||||
|
void(*cb_invoker_)(int ev_type, void* data, unsigned int* len, void* param);
|
||||||
|
void* cb_param_;
|
||||||
int ex_id_;
|
int ex_id_;
|
||||||
int prev_start_result_;
|
int prev_start_result_;
|
||||||
int dpi_;
|
int dpi_;
|
||||||
unsigned int img_ind_;
|
unsigned int img_ind_;
|
||||||
std::wstring tmp_path_;
|
std::wstring tmp_path_;
|
||||||
|
twain_xfer xfer_;
|
||||||
|
safe_img_queue images_;
|
||||||
|
volatile bool working_;
|
||||||
SANE_FinalImgFormat img_fmt_;
|
SANE_FinalImgFormat img_fmt_;
|
||||||
|
|
||||||
int open(void);
|
int open(void);
|
||||||
|
@ -264,11 +269,16 @@ public:
|
||||||
SANE_OPTION_ID(ex_ip); // std::string
|
SANE_OPTION_ID(ex_ip); // std::string
|
||||||
|
|
||||||
// ui ...
|
// ui ...
|
||||||
COM_API_OVERRIDE(void, ui_show_main(void));
|
COM_API_OVERRIDE(bool, ui_show_main(HWND parent));
|
||||||
COM_API_OVERRIDE(void, ui_show_setting(bool with_scan));
|
COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan));
|
||||||
COM_API_OVERRIDE(void, ui_show_progress(void));
|
COM_API_OVERRIDE(bool, ui_show_progress(HWND parent));
|
||||||
COM_API_OVERRIDE(void, ui_hide(void));
|
COM_API_OVERRIDE(void, ui_hide(void));
|
||||||
COM_API_OVERRIDE(void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len));
|
|
||||||
COM_API_OVERRIDE(bool, ui_is_ok(void));
|
COM_API_OVERRIDE(bool, ui_is_ok(void));
|
||||||
COM_API_OVERRIDE(bool, ui_is_progress_ui_showing(void));
|
|
||||||
|
// twain
|
||||||
|
COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer));
|
||||||
|
|
||||||
|
// methods:
|
||||||
|
public:
|
||||||
|
int handle_event(int ev_code, void* data, unsigned int* len);
|
||||||
};
|
};
|
|
@ -837,8 +837,11 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui)
|
||||||
{
|
{
|
||||||
if (!ui.showUi())
|
if (!ui.showUi())
|
||||||
{
|
{
|
||||||
if (m_bIndicator)
|
if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw()))
|
||||||
scanner_->ui_show_main();
|
return seqError();
|
||||||
|
|
||||||
|
scanner_->twain_set_transfer((twain_xfer)m_capXferMech);
|
||||||
|
|
||||||
return scanner_->start() == SCANNER_ERR_OK ? success() : seqError();
|
return scanner_->start() == SCANNER_ERR_OK ? success() : seqError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,12 +1130,7 @@ Result huagao_ds::capCommon(const Identity&, Msg msg, Capability& data) {
|
||||||
Twpp::Result huagao_ds::showTwainUI(Twpp::UserInterface& data, bool bUiOnly)
|
Twpp::Result huagao_ds::showTwainUI(Twpp::UserInterface& data, bool bUiOnly)
|
||||||
{
|
{
|
||||||
// display user UI ... (setting UI, can we show my own main window here ?)
|
// display user UI ... (setting UI, can we show my own main window here ?)
|
||||||
if (bUiOnly)
|
return scanner_->ui_show_setting((HWND)data.parent().raw(), !bUiOnly) ? success() : seqError();
|
||||||
scanner_->ui_show_setting(false);
|
|
||||||
else
|
|
||||||
scanner_->ui_show_main();
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
}
|
||||||
void huagao_ds::init_support_caps(void)
|
void huagao_ds::init_support_caps(void)
|
||||||
{
|
{
|
||||||
|
@ -1178,10 +1176,21 @@ void huagao_ds::init_support_caps(void)
|
||||||
return oneValGetSet<Int16>(msg, data, tmp_count, -1);
|
return oneValGetSet<Int16>(msg, data, tmp_count, -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (scanner_->ui_is_ok())
|
m_bIndicator = scanner_->ui_is_ok();
|
||||||
|
if (m_bIndicator)
|
||||||
{
|
{
|
||||||
m_query[CapType::UiControllable] = msgSupportGetAll;
|
m_query[CapType::UiControllable] = msgSupportGetAll;
|
||||||
m_caps[CapType::UiControllable] = std::bind(oneValGet<Bool>, _1, _2, Bool(true));
|
m_caps[CapType::UiControllable] = std::bind(oneValGet<Bool>, _1, _2, Bool(true));
|
||||||
|
|
||||||
|
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
|
||||||
|
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
|
||||||
|
if (Msg::Set == msg) {
|
||||||
|
auto show = data.currentItem<CapType::Indicators>();
|
||||||
|
m_bIndicator = show;
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
return CapSupGetAllReset<bool, Bool, CapType::Indicators>(msg, data, { FALSE,TRUE }, m_bIndicator, TRUE, m_bIndicator ? 1 : 0, 1);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_query[CapType::DeviceOnline] = msgSupportGetAll;
|
m_query[CapType::DeviceOnline] = msgSupportGetAll;
|
||||||
|
@ -1945,16 +1954,6 @@ void huagao_ds::init_support_caps(void)
|
||||||
return CapSupGetAll<Bool, Bool, CapType::FeederLoaded>(msg, data, paperon, paperon);
|
return CapSupGetAll<Bool, Bool, CapType::FeederLoaded>(msg, data, paperon, paperon);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
|
|
||||||
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
|
|
||||||
if (Msg::Set == msg) {
|
|
||||||
auto show = data.currentItem<CapType::Indicators>();
|
|
||||||
m_bIndicator = show;
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
return CapSupGetAllReset<bool, Bool, CapType::Indicators>(msg, data, { FALSE,TRUE }, m_bIndicator, TRUE, m_bIndicator ? 1 : 0, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
m_query[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = msgSupportGetAllSetReset;
|
m_query[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = msgSupportGetAllSetReset;
|
||||||
m_caps[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = [this](Msg msg, Capability& data)->Result {
|
m_caps[CapType(CapTypeEx::CAP_TYPE_EX_FOLD)] = [this](Msg msg, Capability& data)->Result {
|
||||||
if (Msg::Set == msg || Msg::Reset == msg) {
|
if (Msg::Set == msg || Msg::Reset == msg) {
|
||||||
|
@ -2470,18 +2469,9 @@ void huagao_ds::on_scan_event(int sane_event, void* data, unsigned int* len)
|
||||||
{
|
{
|
||||||
if (scanner_.get())
|
if (scanner_.get())
|
||||||
{
|
{
|
||||||
scanner_->ui_handle_sane_event(sane_event, data, len);
|
|
||||||
if (sane_event == SANE_EVENT_SCAN_FINISHED)
|
if (sane_event == SANE_EVENT_SCAN_FINISHED)
|
||||||
{
|
{
|
||||||
if (scanner_->ui_is_progress_ui_showing())
|
notifyCloseOk();
|
||||||
scanner_->ui_hide();
|
|
||||||
else //if (!scanner_->twain_get_to_be_scan())
|
|
||||||
{
|
|
||||||
bool now = false;
|
|
||||||
GET_SANE_OPT(bool, scanner_, ex_to_be_scan, &now, NULL, NULL, NULL);
|
|
||||||
if(!now)
|
|
||||||
scanner_->ui_hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue