code_device/hgdriver/hgdev/hg_scanner.cpp

312 lines
5.7 KiB
C++

#include "hg_scanner.h"
#include "scanner_manager.h"
#include <sane_opt_json/device_opt.h>
#include <imgprc/imgprc_mgr.h>
#include <lang/app_language.h>
#include "./scanner/scanner_handler.h"
#include "user-opt/user.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// img_receiver
img_receiver::img_receiver(LPPACKIMAGE head, size_t info_size, size_t size, std::function<void(img_receiver*)> complete_routine, uint32_t id)
: id_(id), head_(*head), info_size_(info_size)
, size_(size), finish_(complete_routine)
{
buf_ = (uint8_t*)malloc(size);
if (buf_)
memset(buf_, 0, size);
}
img_receiver::~img_receiver()
{
if (buf_)
free(buf_);
buf_ = nullptr;
}
int img_receiver::put_data(const void* data, uint32_t* size)
{
size_t info = 0;
if (info_.length() < info_size_)
{
size_t need = info_size_ - info_.length();
if (need > *size)
{
info = *size;
info_ += std::string((const char*)data, *size);
*size = 0;
}
else
{
info_ += std::string((const char*)data, need);
*size -= need;
info = need;
}
}
if (*size)
{
if (*size > size_ - wpos_)
*size = size_ - wpos_;
memcpy(buf_ + wpos_, data, *size);
wpos_ += *size;
if (wpos_ >= size_ && finish_)
finish_(this);
}
*size += info;
return 0;
}
bool img_receiver::is_complete(void)
{
return wpos_ >= size_;
}
uint32_t img_receiver::get_required(void)
{
if (wpos_ >= size_)
return 0;
else
return size_ - wpos_ + (info_size_ - info_.length());
}
uint32_t img_receiver::id(void)
{
return id_;
}
size_t img_receiver::size(void)
{
return wpos_;
}
uint8_t* img_receiver::data(void)
{
return buf_;
}
std::string img_receiver::information(void)
{
return info_;
}
PACKIMAGE img_receiver::head(void)
{
return head_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hg_scanner
hg_scanner::hg_scanner(ONLNSCANNER* dev, imgproc_mgr* imgproc, hguser* user, std::vector<sane_opt_provider*>* constopts)
: dev_(*dev), status_(SCANNER_ERR_OPENED_BY_OTHER_PROCESS)
, msg_(from_default_language("\350\256\276\345\244\207\345\267\262\347\273\217\350\242\253\350\277\233\347\250\213 '%s' \345\215\240\347\224\250"))
{
singleton_ = hg_scanner::create_device_singleton(dev_.vid, dev_.pid, dev_.addr);
if (!singleton_->is_first())
{
std::string pre(singleton_->read());
size_t pos = msg_.find("%s");
if (pos == std::string::npos)
msg_ += ": " + pre;
else
msg_.replace(pos, 2, pre);
singleton_->release();
}
else
{
set_where(dev->display_name.c_str());
user_ = user;
init();
if (status() == SCANNER_ERR_OK)
{
imgproc_ = imgproc;
imgproc_->add_ref();
dev_opts_->add(imgproc_);
if (constopts)
{
for(auto& v: *constopts)
dev_opts_->add(v);
}
imgpr_thread_.reset(new std::thread(&hg_scanner::thread_image_processor, this));
}
}
}
hg_scanner::~hg_scanner()
{
close();
}
shared_memory* hg_scanner::create_device_singleton(int vid, int pid, int addr)
{
unsigned long long key = vid;
key <<= 16;
key |= pid;
key <<= 16;
key |= addr;
return new shared_memory(key);
}
void hg_scanner::init(void)
{
auto on_status = [this](uint32_t statu) ->void
{
//status_ = statu;
};
auto on_image_received = [this](LPPACKIMAGE pimg, uint64_t size) ->data_holder_ptr
{
data_holder_ptr pdh = nullptr;
return pdh;
};
auto privilege = [this](int priv) -> bool
{
return user_->has_privilege(priv);
};
auto privilege_empty = [this](int priv) -> bool
{
return true;
};
auto logmsg = [&](const char* msg) -> void
{
utils::to_log(LOG_LEVEL_DEBUG, msg);
};
scanner_ = new scanner_handler();
scanner_->set_image_receiver(on_image_received);
scanner_->set_status_notifyer(on_status);
std::string opts("");
int ret = scanner_->option_get_all(opts);
if (ret == SCANNER_ERR_OK)
{
set_opt_json_text(&opts[0]);
if(user_)
dev_opts_ = new device_option(privilege, logmsg);
else
dev_opts_ = new device_option(privilege_empty, logmsg);
dev_opts_->add(this);
}
else
{
status_ = ret;
}
}
void hg_scanner::thread_image_processor(void)
{
imgproc_mgr * processor = imgproc_;
img_receiver* raw = nullptr;
processor->add_ref();
while (raw_imgs_.take(raw, true))
{
}
processor->release();
}
int hg_scanner::start(void)
{
int ret = SCANNER_ERR_OK;
cancelled_ = false;
if (scanner_)
ret = scanner_->scan_start();
return ret;
}
int hg_scanner::stop(void)
{
int ret = SCANNER_ERR_OK;
cancelled_ = true;
if (scanner_)
ret = scanner_->scan_stop();
return ret;
}
int hg_scanner::close(void)
{
int ret = SCANNER_ERR_OK;
if (scanner_)
{
ret = scanner_->close();
if (ret)
return ret;
scanner_->release();
scanner_ = nullptr;
}
if (dev_opts_)
{
dev_opts_->clear();
dev_opts_->release();
dev_opts_ = nullptr;
}
if (singleton_)
{
singleton_->release();
singleton_ = nullptr;
}
// wait image thread ...
if (imgpr_thread_.get() && imgpr_thread_->joinable())
imgpr_thread_->join();
if (imgproc_)
{
imgproc_->release();
imgproc_ = nullptr;
}
user_ = nullptr;
return ret;
}
int hg_scanner::re_connect(void)
{
return SCANNER_ERR_OK;
}
int hg_scanner::get_image_info(SANE_Parameters* pii)
{
return SCANNER_ERR_OK;
}
int hg_scanner::read_image_data(uint8_t* buf, size_t* len)
{
return SCANNER_ERR_OK;
}
int hg_scanner::status(void)
{
return status_;
}
std::string hg_scanner::status_message(void)
{
return msg_;
}
bool hg_scanner::is_online(void)
{
return online_;
}
device_option* hg_scanner::get_device_opt(void)
{
dev_opts_->add_ref();
return dev_opts_;
}