184 lines
6.3 KiB
C++
184 lines
6.3 KiB
C++
#pragma once
|
||
|
||
#include "scanned_img.h"
|
||
#include <vector>
|
||
#include <algorithm>
|
||
#include <memory>
|
||
#include <functional>
|
||
#include <map>
|
||
#include <thread>
|
||
|
||
|
||
|
||
#define EXTENSION_ID_BASE 0x300
|
||
|
||
class scanner : public ISaneInvoker, virtual public refer
|
||
{
|
||
SANE_Handle handle_;
|
||
std::string model_;
|
||
int err_;
|
||
int ex_id_;
|
||
int prev_start_result_;
|
||
int dpi_;
|
||
int fetch_imgs_ = 0; // count for images has fetched by APP
|
||
bool is_bIndicator;
|
||
bool is_show_setting_;
|
||
unsigned int img_ind_;
|
||
std::string scanner_name_;
|
||
std::string tmp_path_;
|
||
std::string cfg_path_;
|
||
std::string scan_msg_;
|
||
bool scan_err_;
|
||
volatile bool is_ui_wait_img_;
|
||
volatile bool is_scanning_;
|
||
volatile bool user_cancel_;
|
||
twain_xfer xfer_;
|
||
safe_img_queue images_;
|
||
size_t max_img_mem_;
|
||
safe_queue<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件
|
||
int ev_cnt_;
|
||
SANE_FinalImgFormat img_fmt_;
|
||
bool twain_set_;
|
||
SANEAPI sane_api_;
|
||
std::unique_ptr<std::thread> done_;
|
||
std::function<void(int, void*, int)> ui_notify;
|
||
int(* scanner_ev_handler_)(int, void*);
|
||
void* evh_param_;
|
||
HWND app_wnd_; // for MessageBox
|
||
bool is_show_ui_;
|
||
|
||
typedef struct _sane_opt
|
||
{
|
||
int opt_sn;
|
||
value_type type;
|
||
value_limit limit;
|
||
int size;
|
||
int cap; // sane capability
|
||
}SANEOPT;
|
||
std::map<int, SANEOPT> sane_opts_; // <fix-id, SANEOPT>
|
||
|
||
|
||
int transfer_id(int id); // transfer fixed SANE option ID to real id, -1 is none
|
||
void transport_config_file(void);
|
||
void update_config(void);
|
||
void load_config(const wchar_t* file);
|
||
void save_config(const wchar_t* file);
|
||
void apply_config(void);
|
||
void on_ui_event(int uev, void* sender);
|
||
std::string choose_scanner(const std::vector<std::string>& scanners);
|
||
int close(void);
|
||
int init_options_id(void);
|
||
char* get_opt_value(int id, int size, bool def_val/*false - current value*/); // call delete[] to free returned value
|
||
bool get_opt_value(int id, void* buf, bool def_val/*false - current value*/); // call delete[] to free returned value
|
||
int control_read_string(int io_code, std::string& val);
|
||
|
||
bool get_option_value_with_parent(int sn, set_opt_value setv, void* param); // return true if handled
|
||
bool set_option_value_with_parent(int sn, void* data, int* err); // return true if handled sn
|
||
int set_option_value(int sn, SANE_Value_Type type, int size, void* data);
|
||
|
||
int thread_start(void);
|
||
std::unique_ptr<std::thread> thread_starting_;
|
||
std::unique_ptr<std::thread> thread_stop_; // stop阻塞到工作线程结束,在结束回调后才返回。为不阻塞界面,在线程中停止
|
||
bool scan_working_ = false; // start阻塞到有一张图片才返回,如果第一张出现错误(比如卡纸),则回调先于start返回结束标志。该变量用于协调FINISH事件通知
|
||
|
||
|
||
template<class T>
|
||
bool set_cur_and_def_value(T cur, T def, set_opt_value setv, void* param)
|
||
{
|
||
if (cur == def)
|
||
return setv(&cur, (value_role)(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), VAL_LIMIT_NONE, param);
|
||
else if (setv(&cur, VAL_ROLE_CURRENT, VAL_LIMIT_NONE, param))
|
||
return setv(&def, VAL_ROLE_DEFAULT, VAL_LIMIT_NONE, param);
|
||
|
||
return false;
|
||
}
|
||
template<class S, class T>
|
||
void set_value_range(S cur, S def, S l, S u, S s, set_opt_value setv, void* param, T(* to_t)(S))
|
||
{
|
||
T v = to_t(cur);
|
||
while (setv(&v, VAL_ROLE_CURRENT, VAL_LIMIT_RANGE, param))
|
||
{
|
||
v = to_t(def);
|
||
if (!setv(&v, VAL_ROLE_DEFAULT, VAL_LIMIT_RANGE, param))
|
||
break;
|
||
|
||
v = to_t(l);
|
||
if (!setv(&v, VAL_ROLE_LOWER, VAL_LIMIT_RANGE, param))
|
||
break;
|
||
v = to_t(u);
|
||
if (!setv(&v, VAL_ROLE_UPPER, VAL_LIMIT_RANGE, param))
|
||
break;
|
||
v = to_t(s);
|
||
setv(&v, VAL_ROLE_STEP, VAL_LIMIT_RANGE, param);
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
static int to_int(SANE_Int v);
|
||
static double to_double(SANE_Fixed v);
|
||
static void ui_callback(int uev, void* sender, void* param);
|
||
static bool is_option_float(int sn, void* param);
|
||
|
||
void scan_done(void);
|
||
|
||
int language_id_;
|
||
|
||
public:
|
||
scanner(const char* model);
|
||
|
||
protected:
|
||
~scanner();
|
||
|
||
public:
|
||
static void get_scanner_name(const char* model, std::vector<std::string>& names);
|
||
static value_type from_sane_type(SANE_Value_Type type);
|
||
static value_limit from_sane_constraint(SANE_Constraint_Type type);
|
||
|
||
// IRef
|
||
public:
|
||
COM_API_OVERRIDE(int32_t, add_ref(void));
|
||
COM_API_OVERRIDE(int32_t, release(void));
|
||
|
||
// ISaneInvoker
|
||
public:
|
||
COM_API_OVERRIDE(int, start(void));
|
||
COM_API_OVERRIDE(int, stop(void));
|
||
COM_API_OVERRIDE(int, get_event(void));
|
||
COM_API_OVERRIDE(void, set_event_callback(int(*handle_ev)(int, void*) = nullptr, void* para = nullptr));
|
||
COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1));
|
||
COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0));
|
||
COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz
|
||
COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = nullptr, int* dpi = nullptr));
|
||
COM_API_OVERRIDE(bool, discard_first_image(void));
|
||
COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv));
|
||
COM_API_OVERRIDE(bool, is_online(void));
|
||
COM_API_OVERRIDE(bool, is_paper_on(void));
|
||
COM_API_OVERRIDE(int, last_error(void));
|
||
COM_API_OVERRIDE(int, image_fetched(IScanImg* tx)); // notify the image 'tx' has fetched by APP
|
||
|
||
// ui ...
|
||
COM_API_OVERRIDE(bool, ui_is_ok(void));
|
||
COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true));
|
||
COM_API_OVERRIDE(bool, ui_show_progress(HWND parent, bool bIndicator));
|
||
COM_API_OVERRIDE(void, ui_hide(void));
|
||
|
||
// twain
|
||
COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer));
|
||
COM_API_OVERRIDE(void, twain_set_compression(SANE_CompressionType compression, void* detail = nullptr));
|
||
COM_API_OVERRIDE(int, twain_get_config(char* buf, size_t* len));
|
||
COM_API_OVERRIDE(int, twain_set_config(char* buf, size_t len));
|
||
|
||
COM_API_OVERRIDE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes, bool* readonly));
|
||
COM_API_OVERRIDE(int, get_fixed_ids(SANE_Bool(*cb)(int id, void* param), void* param));
|
||
|
||
COM_API_OVERRIDE(bool, get_value(int sn, set_opt_value func, void* param)); // get all values
|
||
COM_API_OVERRIDE(bool, get_value(int sn, void* data, int* len)); // get current value
|
||
COM_API_OVERRIDE(int, set_value(int sn, void* val));
|
||
|
||
// methods:
|
||
public:
|
||
int open(void);
|
||
int handle_device_event(int ev_code, void* data, unsigned int* len);
|
||
};
|