181 lines
4.0 KiB
C++
181 lines
4.0 KiB
C++
#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<OPTVAL>& 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_ = "";
|
|
}
|