code_device/twain/ds/scanner.h

184 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
};