#include "sane_device.h" sane_dev::sane_dev() : hdev_(nullptr), offline_(true), name_(""), cfg_name_("") {} sane_dev::~sane_dev() { close(); } bool sane_dev::apply(OPTSCHEME* schm) { SANE_Int count = 0, afterdo = 0; bool ret = false; if(sane_control_option(hdev_, 0, SANE_ACTION_GET_VALUE, &count, &afterdo) == SANE_STATUS_GOOD) { int applied = 0; for(int i = 1; i < count; ++i) { const SANE_Option_Descriptor* desc = sane_get_option_descriptor(hdev_, i); if(!desc) continue; if(desc->type == SANE_TYPE_GROUP || desc->type == SANE_TYPE_BUTTON) continue; act_result result = apply(desc, i, schm->opts); if(result == ACT_RESULT_NO_NEED) continue; if(result == ACT_RESULT_SUCCESS) applied++; else break; } ret = schm->opts.size() == applied; } if(ret) cfg_name_ = schm->name; return ret; } sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector& vals) { act_result result = ACT_RESULT_NO_NEED; const OPTVAL *cfg = nullptr; for(size_t i = 0; i < vals.size(); ++i) { if(vals[i].name == desc->title) { cfg = &vals[i]; break; } } if(cfg) { SANE_Int afterdo = 0; void *data = nullptr, *str = nullptr; SANE_Int nv = 0; SANE_Bool bv = false; SANE_Fixed fv = 0; result = ACT_RESULT_FAILED; if(desc->type == SANE_TYPE_INT) { nv = atoi(cfg->val.c_str()); data = &nv; } else if(desc->type == SANE_TYPE_BOOL) { bv = cfg->val == "true"; data = &bv; } else if(desc->type == SANE_TYPE_FIXED) { fv = SANE_FIX(atof(cfg->val.c_str())); data = &fv; } else if(desc->type == SANE_TYPE_STRING) { int len = (int)cfg->val.length() > desc->size * 4 ? cfg->val.length() : desc->size * 4; str = new char[len + 4]; if(str) { memset(str, 0, len + 4); strcpy((char*)str, cfg->val.c_str()); data = str; } } if(data) result = sane_control_option(hdev_, opt, SANE_ACTION_SET_VALUE, data, &afterdo) == SANE_STATUS_GOOD ? ACT_RESULT_SUCCESS : result; if(str) delete[] str; } return result; } std::string sane_dev::name(void) { return name_; } std::string sane_dev::current_configuration_name(void) { return cfg_name_; } bool sane_dev::is_online(void) { return !offline_; } SANE_Handle sane_dev::handle(void) { return hdev_; } bool sane_dev::open(const std::string& name) { if(name_ == name) return true; close(); SANE_Status statu = sane_open(name.c_str(), &hdev_); if(statu == SANE_STATUS_GOOD) { DEVCFG first; name_ = name; offline_ = false; if(first.schemes.size()) cfg_name_ = first.schemes[0].name; } return statu == SANE_STATUS_GOOD; } bool sane_dev::apply_setting(OPTSCHEME* schm) { bool ret = false; if(hdev_) { if(sane_io_control(hdev_, IO_CTRL_CODE_RESTORE_SETTINGS, nullptr, nullptr) == SANE_STATUS_GOOD) { DEVCFG first; if(first.schemes.size()) cfg_name_ = first.schemes[0].name; if(schm) { ret = apply(schm); } else { ret = true; } } } return ret; } void sane_dev::set_online(bool online) { offline_ = !online; } void sane_dev::close(void) { if(hdev_) { sane_close(hdev_); hdev_ = nullptr; } offline_ = true; name_ = ""; cfg_name_ = ""; }