genesys: Prefer to have a local `dev` variable for Genesys_Device*

merge-requests/463/merge
Povilas Kanapickas 2020-05-21 23:40:55 +03:00
rodzic b6eb01cd0f
commit 0957103cc3
1 zmienionych plików z 243 dodań i 252 usunięć

Wyświetl plik

@ -4249,6 +4249,9 @@ static unsigned pick_resolution(const std::vector<unsigned>& resolutions, unsign
static void calc_parameters(Genesys_Scanner* s) static void calc_parameters(Genesys_Scanner* s)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
auto* dev = s->dev;
float tl_x = 0, tl_y = 0, br_x = 0, br_y = 0; float tl_x = 0, tl_y = 0, br_x = 0, br_y = 0;
tl_x = fixed_to_float(s->pos_top_left_x); tl_x = fixed_to_float(s->pos_top_left_x);
@ -4270,47 +4273,45 @@ static void calc_parameters(Genesys_Scanner* s)
s->params.depth = s->bit_depth; s->params.depth = s->bit_depth;
} }
s->dev->settings.scan_method = s->scan_method; dev->settings.scan_method = s->scan_method;
const auto& resolutions = s->dev->model->get_resolution_settings(s->dev->settings.scan_method); const auto& resolutions = dev->model->get_resolution_settings(dev->settings.scan_method);
s->dev->settings.depth = s->bit_depth; dev->settings.depth = s->bit_depth;
dev->settings.disable_interpolation = s->disable_interpolation;
/* interpolation */ // FIXME: use correct sensor
s->dev->settings.disable_interpolation = s->disable_interpolation; const auto& sensor = sanei_genesys_find_sensor_any(dev);
// FIXME: use correct sensor
const auto& sensor = sanei_genesys_find_sensor_any(s->dev);
// hardware settings // hardware settings
if (static_cast<unsigned>(s->resolution) > sensor.full_resolution && if (static_cast<unsigned>(s->resolution) > sensor.full_resolution &&
s->dev->settings.disable_interpolation) dev->settings.disable_interpolation)
{ {
s->dev->settings.xres = sensor.full_resolution; dev->settings.xres = sensor.full_resolution;
} else { } else {
s->dev->settings.xres = s->resolution; dev->settings.xres = s->resolution;
} }
s->dev->settings.yres = s->resolution; dev->settings.yres = s->resolution;
s->dev->settings.xres = pick_resolution(resolutions.resolutions_x, s->dev->settings.xres, "X"); dev->settings.xres = pick_resolution(resolutions.resolutions_x, dev->settings.xres, "X");
s->dev->settings.yres = pick_resolution(resolutions.resolutions_y, s->dev->settings.yres, "Y"); dev->settings.yres = pick_resolution(resolutions.resolutions_y, dev->settings.yres, "Y");
s->params.lines = static_cast<unsigned>(((br_y - tl_y) * s->dev->settings.yres) / s->params.lines = static_cast<unsigned>(((br_y - tl_y) * dev->settings.yres) /
MM_PER_INCH); MM_PER_INCH);
unsigned pixels_per_line = static_cast<unsigned>(((br_x - tl_x) * s->dev->settings.xres) / unsigned pixels_per_line = static_cast<unsigned>(((br_x - tl_x) * dev->settings.xres) /
MM_PER_INCH); MM_PER_INCH);
/* we need an even pixels number /* we need an even pixels number
* TODO invert test logic or generalize behaviour across all ASICs */ * TODO invert test logic or generalize behaviour across all ASICs */
if (has_flag(s->dev->model->flags, ModelFlag::SIS_SENSOR) || if (has_flag(dev->model->flags, ModelFlag::SIS_SENSOR) ||
s->dev->model->asic_type == AsicType::GL847 || dev->model->asic_type == AsicType::GL847 ||
s->dev->model->asic_type == AsicType::GL124 || dev->model->asic_type == AsicType::GL124 ||
s->dev->model->asic_type == AsicType::GL845 || dev->model->asic_type == AsicType::GL845 ||
s->dev->model->asic_type == AsicType::GL846 || dev->model->asic_type == AsicType::GL846 ||
s->dev->model->asic_type == AsicType::GL843) dev->model->asic_type == AsicType::GL843)
{ {
if (s->dev->settings.xres <= 1200) { if (dev->settings.xres <= 1200) {
pixels_per_line = (pixels_per_line / 4) * 4; pixels_per_line = (pixels_per_line / 4) * 4;
} else if (s->dev->settings.xres < s->dev->settings.yres) { } else if (dev->settings.xres < dev->settings.yres) {
// BUG: this is an artifact of the fact that the resolution was twice as large than // BUG: this is an artifact of the fact that the resolution was twice as large than
// the actual resolution when scanning above the supported scanner X resolution // the actual resolution when scanning above the supported scanner X resolution
pixels_per_line = (pixels_per_line / 8) * 8; pixels_per_line = (pixels_per_line / 8) * 8;
@ -4321,12 +4322,12 @@ static void calc_parameters(Genesys_Scanner* s)
/* corner case for true lineart for sensor with several segments /* corner case for true lineart for sensor with several segments
* or when xres is doubled to match yres */ * or when xres is doubled to match yres */
if (s->dev->settings.xres >= 1200 && ( if (dev->settings.xres >= 1200 && (
s->dev->model->asic_type == AsicType::GL124 || dev->model->asic_type == AsicType::GL124 ||
s->dev->model->asic_type == AsicType::GL847 || dev->model->asic_type == AsicType::GL847 ||
s->dev->session.params.xres < s->dev->session.params.yres)) dev->session.params.xres < dev->session.params.yres))
{ {
if (s->dev->settings.xres < s->dev->settings.yres) { if (dev->settings.xres < dev->settings.yres) {
// FIXME: this is an artifact of the fact that the resolution was twice as large than // FIXME: this is an artifact of the fact that the resolution was twice as large than
// the actual resolution when scanning above the supported scanner X resolution // the actual resolution when scanning above the supported scanner X resolution
pixels_per_line = (pixels_per_line / 8) * 8; pixels_per_line = (pixels_per_line / 8) * 8;
@ -4335,17 +4336,14 @@ static void calc_parameters(Genesys_Scanner* s)
} }
} }
unsigned xres_factor = s->resolution / s->dev->settings.xres; unsigned xres_factor = s->resolution / dev->settings.xres;
unsigned bytes_per_line = 0; unsigned bytes_per_line = 0;
if (s->params.depth > 8) if (s->params.depth > 8) {
{ s->params.depth = 16;
s->params.depth = 16;
bytes_per_line = 2 * pixels_per_line; bytes_per_line = 2 * pixels_per_line;
} } else if (s->params.depth == 1) {
else if (s->params.depth == 1)
{
// round down pixel number. This will is lossy operation, at most 7 pixels will be lost // round down pixel number. This will is lossy operation, at most 7 pixels will be lost
pixels_per_line = (pixels_per_line / 8) * 8; pixels_per_line = (pixels_per_line / 8) * 8;
bytes_per_line = pixels_per_line / 8; bytes_per_line = pixels_per_line / 8;
@ -4357,54 +4355,46 @@ static void calc_parameters(Genesys_Scanner* s)
bytes_per_line *= 3; bytes_per_line *= 3;
} }
s->dev->settings.scan_mode = option_string_to_scan_color_mode(s->mode); dev->settings.scan_mode = option_string_to_scan_color_mode(s->mode);
s->dev->settings.lines = s->params.lines; dev->settings.lines = s->params.lines;
s->dev->settings.pixels = pixels_per_line; dev->settings.pixels = pixels_per_line;
s->dev->settings.requested_pixels = pixels_per_line * xres_factor; dev->settings.requested_pixels = pixels_per_line * xres_factor;
s->params.pixels_per_line = pixels_per_line * xres_factor; s->params.pixels_per_line = pixels_per_line * xres_factor;
s->params.bytes_per_line = bytes_per_line * xres_factor; s->params.bytes_per_line = bytes_per_line * xres_factor;
s->dev->settings.tl_x = tl_x; dev->settings.tl_x = tl_x;
s->dev->settings.tl_y = tl_y; dev->settings.tl_y = tl_y;
// threshold setting dev->settings.threshold = static_cast<int>(2.55f * (fixed_to_float(s->threshold)));
s->dev->settings.threshold = static_cast<int>(2.55f * (fixed_to_float(s->threshold)));
// color filter
if (s->color_filter == "Red") { if (s->color_filter == "Red") {
s->dev->settings.color_filter = ColorFilter::RED; dev->settings.color_filter = ColorFilter::RED;
} else if (s->color_filter == "Green") { } else if (s->color_filter == "Green") {
s->dev->settings.color_filter = ColorFilter::GREEN; dev->settings.color_filter = ColorFilter::GREEN;
} else if (s->color_filter == "Blue") { } else if (s->color_filter == "Blue") {
s->dev->settings.color_filter = ColorFilter::BLUE; dev->settings.color_filter = ColorFilter::BLUE;
} else { } else {
s->dev->settings.color_filter = ColorFilter::NONE; dev->settings.color_filter = ColorFilter::NONE;
} }
// true gray
if (s->color_filter == "None") { if (s->color_filter == "None") {
s->dev->settings.true_gray = 1; dev->settings.true_gray = 1;
} else { } else {
s->dev->settings.true_gray = 0; dev->settings.true_gray = 0;
} }
// threshold curve for dynamic rasterization dev->settings.threshold_curve = s->threshold_curve;
s->dev->settings.threshold_curve = s->threshold_curve;
/* brigthness and contrast only for for 8 bit scans */ // brigthness and contrast only for for 8 bit scans
if(s->bit_depth <= 8) if (s->bit_depth <= 8) {
{ dev->settings.contrast = (s->contrast * 127) / 100;
s->dev->settings.contrast = (s->contrast * 127) / 100; dev->settings.brightness = (s->brightness * 127) / 100;
s->dev->settings.brightness = (s->brightness * 127) / 100; } else {
} dev->settings.contrast=0;
else dev->settings.brightness=0;
{
s->dev->settings.contrast=0;
s->dev->settings.brightness=0;
} }
/* cache expiration time */ dev->settings.expiration_time = s->expiration_time;
s->dev->settings.expiration_time = s->expiration_time;
} }
@ -5536,12 +5526,12 @@ static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
s_scanners->push_back(Genesys_Scanner()); s_scanners->push_back(Genesys_Scanner());
auto* s = &s_scanners->back(); auto* s = &s_scanners->back();
s->dev = dev; s->dev = dev;
s->scanning = false; s->scanning = false;
s->dev->parking = false; dev->parking = false;
s->dev->read_active = false; dev->read_active = false;
s->dev->force_calibration = 0; dev->force_calibration = 0;
s->dev->line_count = 0; dev->line_count = 0;
*handle = s; *handle = s;
@ -5553,14 +5543,14 @@ static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
DBG_INIT(); DBG_INIT();
s->dev->cmd_set = create_cmd_set(s->dev->model->asic_type); dev->cmd_set = create_cmd_set(dev->model->asic_type);
// FIXME: we create sensor tables for the sensor, this should happen when we know which sensor // FIXME: we create sensor tables for the sensor, this should happen when we know which sensor
// we will select // we will select
dev->cmd_set->init(dev); dev->cmd_set->init(dev);
// some hardware capabilities are detected through sensors // some hardware capabilities are detected through sensors
s->dev->cmd_set->update_hardware_sensors (s); dev->cmd_set->update_hardware_sensors (s);
} }
SANE_GENESYS_API_LINKAGE SANE_GENESYS_API_LINKAGE
@ -5592,46 +5582,42 @@ sane_close_impl(SANE_Handle handle)
return; /* oops, not a handle we know about */ return; /* oops, not a handle we know about */
} }
Genesys_Scanner* s = &*it; auto* dev = it->dev;
/* eject document for sheetfed scanners */ // eject document for sheetfed scanners
if (s->dev->model->is_sheetfed) { if (dev->model->is_sheetfed) {
catch_all_exceptions(__func__, [&](){ s->dev->cmd_set->eject_document(s->dev); }); catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
} } else {
else // in case scanner is parking, wait for the head to reach home position
{ if (dev->parking) {
/* in case scanner is parking, wait for the head sanei_genesys_wait_for_home(dev);
* to reach home position */
if (s->dev->parking) {
sanei_genesys_wait_for_home(s->dev);
} }
} }
// enable power saving before leaving // enable power saving before leaving
s->dev->cmd_set->save_power(s->dev, true); dev->cmd_set->save_power(dev, true);
// here is the place to store calibration cache // here is the place to store calibration cache
if (s->dev->force_calibration == 0 && !is_testing_mode()) { if (dev->force_calibration == 0 && !is_testing_mode()) {
catch_all_exceptions(__func__, [&](){ write_calibration(s->dev->calibration_cache, catch_all_exceptions(__func__, [&](){ write_calibration(dev->calibration_cache,
s->dev->calib_file); }); dev->calib_file); });
} }
s->dev->already_initialized = false; dev->already_initialized = false;
dev->clear();
s->dev->clear();
// LAMP OFF : same register across all the ASICs */ // LAMP OFF : same register across all the ASICs */
s->dev->interface->write_register(0x03, 0x00); dev->interface->write_register(0x03, 0x00);
catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().clear_halt(); }); catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().clear_halt(); });
// we need this to avoid these ASIC getting stuck in bulk writes // we need this to avoid these ASIC getting stuck in bulk writes
catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().reset(); }); catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().reset(); });
// not freeing s->dev because it's in the dev list // not freeing dev because it's in the dev list
catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().close(); }); catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().close(); });
s_scanners->erase(it); s_scanners->erase(it);
} }
SANE_GENESYS_API_LINKAGE SANE_GENESYS_API_LINKAGE
@ -5696,18 +5682,19 @@ static void print_option(DebugMessageHelper& dbg, const Genesys_Scanner& s, int
static void get_option_value(Genesys_Scanner* s, int option, void* val) static void get_option_value(Genesys_Scanner* s, int option, void* val)
{ {
DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option); DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
auto* dev = s->dev;
unsigned int i; unsigned int i;
SANE_Word* table = nullptr; SANE_Word* table = nullptr;
std::vector<uint16_t> gamma_table; std::vector<uint16_t> gamma_table;
unsigned option_size = 0; unsigned option_size = 0;
const Genesys_Sensor* sensor = nullptr; const Genesys_Sensor* sensor = nullptr;
if (sanei_genesys_has_sensor(s->dev, s->dev->settings.xres, s->dev->settings.get_channels(), if (sanei_genesys_has_sensor(dev, dev->settings.xres, dev->settings.get_channels(),
s->dev->settings.scan_method)) dev->settings.scan_method))
{ {
sensor = &sanei_genesys_find_sensor(s->dev, s->dev->settings.xres, sensor = &sanei_genesys_find_sensor(dev, dev->settings.xres,
s->dev->settings.get_channels(), dev->settings.get_channels(),
s->dev->settings.scan_method); dev->settings.scan_method);
} }
switch (option) switch (option)
@ -5786,13 +5773,13 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected"); throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val); table = reinterpret_cast<SANE_Word*>(val);
if (s->color_filter == "Red") { if (s->color_filter == "Red") {
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_RED); gamma_table = get_gamma_table(dev, *sensor, GENESYS_RED);
} else if (s->color_filter == "Blue") { } else if (s->color_filter == "Blue") {
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_BLUE); gamma_table = get_gamma_table(dev, *sensor, GENESYS_BLUE);
} else { } else {
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_GREEN); gamma_table = get_gamma_table(dev, *sensor, GENESYS_GREEN);
} }
option_size = s->opt[option].size / sizeof (SANE_Word); option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) { if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match"); throw std::runtime_error("The size of the gamma tables does not match");
@ -5806,7 +5793,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected"); throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val); table = reinterpret_cast<SANE_Word*>(val);
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_RED); gamma_table = get_gamma_table(dev, *sensor, GENESYS_RED);
option_size = s->opt[option].size / sizeof (SANE_Word); option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) { if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match"); throw std::runtime_error("The size of the gamma tables does not match");
@ -5820,7 +5807,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected"); throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val); table = reinterpret_cast<SANE_Word*>(val);
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_GREEN); gamma_table = get_gamma_table(dev, *sensor, GENESYS_GREEN);
option_size = s->opt[option].size / sizeof (SANE_Word); option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) { if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match"); throw std::runtime_error("The size of the gamma tables does not match");
@ -5834,7 +5821,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected"); throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val); table = reinterpret_cast<SANE_Word*>(val);
gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_BLUE); gamma_table = get_gamma_table(dev, *sensor, GENESYS_BLUE);
option_size = s->opt[option].size / sizeof (SANE_Word); option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) { if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match"); throw std::runtime_error("The size of the gamma tables does not match");
@ -5866,11 +5853,10 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
bool result = true; bool result = true;
auto session = s->dev->cmd_set->calculate_scan_session(s->dev, *sensor, auto session = dev->cmd_set->calculate_scan_session(dev, *sensor, dev->settings);
s->dev->settings);
for (auto& cache : s->dev->calibration_cache) { for (auto& cache : dev->calibration_cache) {
if (sanei_genesys_is_compatible_calibration(s->dev, session, &cache, false)) { if (sanei_genesys_is_compatible_calibration(dev, session, &cache, false)) {
*reinterpret_cast<SANE_Bool*>(val) = SANE_FALSE; *reinterpret_cast<SANE_Bool*>(val) = SANE_FALSE;
} }
} }
@ -5889,6 +5875,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
static void set_calibration_value(Genesys_Scanner* s, const char* val) static void set_calibration_value(Genesys_Scanner* s, const char* val)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
auto dev = s->dev;
std::string new_calib_path = val; std::string new_calib_path = val;
Genesys_Device::Calibration new_calibration; Genesys_Device::Calibration new_calibration;
@ -5903,8 +5890,8 @@ static void set_calibration_value(Genesys_Scanner* s, const char* val)
return; return;
} }
s->dev->calibration_cache = std::move(new_calibration); dev->calibration_cache = std::move(new_calibration);
s->dev->calib_file = new_calib_path; dev->calib_file = new_calib_path;
s->calibration_file = new_calib_path; s->calibration_file = new_calib_path;
DBG(DBG_info, "%s: Calibration filename set to '%s':\n", __func__, new_calib_path.c_str()); DBG(DBG_info, "%s: Calibration filename set to '%s':\n", __func__, new_calib_path.c_str());
} }
@ -5915,12 +5902,13 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option); DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
print_option(dbg, *s, option, val); print_option(dbg, *s, option, val);
auto* dev = s->dev;
SANE_Word *table; SANE_Word *table;
unsigned int i; unsigned int i;
unsigned option_size = 0; unsigned option_size = 0;
switch (option) switch (option) {
{
case OPT_TL_X: case OPT_TL_X:
s->pos_top_left_x = *reinterpret_cast<SANE_Word*>(val); s->pos_top_left_x = *reinterpret_cast<SANE_Word*>(val);
calc_parameters(s); calc_parameters(s);
@ -6015,7 +6003,7 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
ENABLE (OPT_THRESHOLD); ENABLE (OPT_THRESHOLD);
ENABLE (OPT_THRESHOLD_CURVE); ENABLE (OPT_THRESHOLD_CURVE);
DISABLE (OPT_BIT_DEPTH); DISABLE (OPT_BIT_DEPTH);
if (s->dev->model->asic_type != AsicType::GL646 || !s->dev->model->is_cis) { if (dev->model->asic_type != AsicType::GL646 || !dev->model->is_cis) {
ENABLE(OPT_COLOR_FILTER); ENABLE(OPT_COLOR_FILTER);
} }
} }
@ -6023,22 +6011,19 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
{ {
DISABLE (OPT_THRESHOLD); DISABLE (OPT_THRESHOLD);
DISABLE (OPT_THRESHOLD_CURVE); DISABLE (OPT_THRESHOLD_CURVE);
if (s->mode == SANE_VALUE_SCAN_MODE_GRAY) if (s->mode == SANE_VALUE_SCAN_MODE_GRAY) {
{ if (dev->model->asic_type != AsicType::GL646 || !dev->model->is_cis) {
if (s->dev->model->asic_type != AsicType::GL646 || !s->dev->model->is_cis) {
ENABLE(OPT_COLOR_FILTER); ENABLE(OPT_COLOR_FILTER);
} }
create_bpp_list (s, s->dev->model->bpp_gray_values); create_bpp_list(s, dev->model->bpp_gray_values);
s->bit_depth = s->dev->model->bpp_gray_values[0]; s->bit_depth = dev->model->bpp_gray_values[0];
} } else {
else DISABLE(OPT_COLOR_FILTER);
{ create_bpp_list(s, dev->model->bpp_color_values);
DISABLE (OPT_COLOR_FILTER); s->bit_depth = dev->model->bpp_color_values[0];
create_bpp_list (s, s->dev->model->bpp_color_values); }
s->bit_depth = s->dev->model->bpp_color_values[0]; }
} calc_parameters(s);
}
calc_parameters(s);
/* if custom gamma, toggle gamma table options according to the mode */ /* if custom gamma, toggle gamma table options according to the mode */
if (s->custom_gamma) if (s->custom_gamma)
@ -6065,24 +6050,26 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
s->color_filter = reinterpret_cast<const char*>(val); s->color_filter = reinterpret_cast<const char*>(val);
calc_parameters(s); calc_parameters(s);
break; break;
case OPT_CALIBRATION_FILE: case OPT_CALIBRATION_FILE: {
if (s->dev->force_calibration == 0) { if (dev->force_calibration == 0) {
set_calibration_value(s, reinterpret_cast<const char*>(val)); set_calibration_value(s, reinterpret_cast<const char*>(val));
} }
break; break;
case OPT_LAMP_OFF_TIME:
if (*reinterpret_cast<SANE_Word*>(val) != s->lamp_off_time) {
s->lamp_off_time = *reinterpret_cast<SANE_Word*>(val);
s->dev->cmd_set->set_powersaving(s->dev, s->lamp_off_time);
} }
break; case OPT_LAMP_OFF_TIME: {
case OPT_EXPIRATION_TIME: if (*reinterpret_cast<SANE_Word*>(val) != s->lamp_off_time) {
if (*reinterpret_cast<SANE_Word*>(val) != s->expiration_time) { s->lamp_off_time = *reinterpret_cast<SANE_Word*>(val);
s->expiration_time = *reinterpret_cast<SANE_Word*>(val); dev->cmd_set->set_powersaving(dev, s->lamp_off_time);
}
break;
} }
break; case OPT_EXPIRATION_TIME: {
if (*reinterpret_cast<SANE_Word*>(val) != s->expiration_time) {
case OPT_CUSTOM_GAMMA: s->expiration_time = *reinterpret_cast<SANE_Word*>(val);
}
break;
}
case OPT_CUSTOM_GAMMA: {
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
s->custom_gamma = *reinterpret_cast<SANE_Bool*>(val); s->custom_gamma = *reinterpret_cast<SANE_Bool*>(val);
@ -6108,88 +6095,96 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_R);
DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_G);
DISABLE (OPT_GAMMA_VECTOR_B); DISABLE (OPT_GAMMA_VECTOR_B);
for (auto& table : s->dev->gamma_override_tables) { for (auto& table : dev->gamma_override_tables) {
table.clear(); table.clear();
}
} }
} break;
break; }
case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR: {
table = reinterpret_cast<SANE_Word*>(val); table = reinterpret_cast<SANE_Word*>(val);
option_size = s->opt[option].size / sizeof (SANE_Word); option_size = s->opt[option].size / sizeof (SANE_Word);
s->dev->gamma_override_tables[GENESYS_RED].resize(option_size); dev->gamma_override_tables[GENESYS_RED].resize(option_size);
s->dev->gamma_override_tables[GENESYS_GREEN].resize(option_size); dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
s->dev->gamma_override_tables[GENESYS_BLUE].resize(option_size); dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
for (i = 0; i < option_size; i++) { for (i = 0; i < option_size; i++) {
s->dev->gamma_override_tables[GENESYS_RED][i] = table[i]; dev->gamma_override_tables[GENESYS_RED][i] = table[i];
s->dev->gamma_override_tables[GENESYS_GREEN][i] = table[i]; dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
s->dev->gamma_override_tables[GENESYS_BLUE][i] = table[i]; dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
}
break;
} }
break; case OPT_GAMMA_VECTOR_R: {
case OPT_GAMMA_VECTOR_R: table = reinterpret_cast<SANE_Word*>(val);
table = reinterpret_cast<SANE_Word*>(val); option_size = s->opt[option].size / sizeof (SANE_Word);
option_size = s->opt[option].size / sizeof (SANE_Word); dev->gamma_override_tables[GENESYS_RED].resize(option_size);
s->dev->gamma_override_tables[GENESYS_RED].resize(option_size); for (i = 0; i < option_size; i++) {
for (i = 0; i < option_size; i++) { dev->gamma_override_tables[GENESYS_RED][i] = table[i];
s->dev->gamma_override_tables[GENESYS_RED][i] = table[i]; }
break;
} }
break; case OPT_GAMMA_VECTOR_G: {
case OPT_GAMMA_VECTOR_G: table = reinterpret_cast<SANE_Word*>(val);
table = reinterpret_cast<SANE_Word*>(val); option_size = s->opt[option].size / sizeof (SANE_Word);
option_size = s->opt[option].size / sizeof (SANE_Word); dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
s->dev->gamma_override_tables[GENESYS_GREEN].resize(option_size); for (i = 0; i < option_size; i++) {
for (i = 0; i < option_size; i++) { dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
s->dev->gamma_override_tables[GENESYS_GREEN][i] = table[i]; }
break;
} }
break; case OPT_GAMMA_VECTOR_B: {
case OPT_GAMMA_VECTOR_B: table = reinterpret_cast<SANE_Word*>(val);
table = reinterpret_cast<SANE_Word*>(val); option_size = s->opt[option].size / sizeof (SANE_Word);
option_size = s->opt[option].size / sizeof (SANE_Word); dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
s->dev->gamma_override_tables[GENESYS_BLUE].resize(option_size); for (i = 0; i < option_size; i++) {
for (i = 0; i < option_size; i++) { dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
s->dev->gamma_override_tables[GENESYS_BLUE][i] = table[i]; }
break;
} }
break;
case OPT_CALIBRATE: { case OPT_CALIBRATE: {
auto& sensor = sanei_genesys_find_sensor_for_write(s->dev, s->dev->settings.xres, auto& sensor = sanei_genesys_find_sensor_for_write(dev, dev->settings.xres,
s->dev->settings.get_channels(), dev->settings.get_channels(),
s->dev->settings.scan_method); dev->settings.scan_method);
catch_all_exceptions(__func__, [&]() catch_all_exceptions(__func__, [&]()
{ {
s->dev->cmd_set->save_power(s->dev, false); dev->cmd_set->save_power(dev, false);
genesys_scanner_calibration(s->dev, sensor); genesys_scanner_calibration(dev, sensor);
}); });
catch_all_exceptions(__func__, [&]() catch_all_exceptions(__func__, [&]()
{ {
s->dev->cmd_set->save_power(s->dev, true); dev->cmd_set->save_power(dev, true);
}); });
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break; break;
} }
case OPT_CLEAR_CALIBRATION: case OPT_CLEAR_CALIBRATION: {
s->dev->calibration_cache.clear(); dev->calibration_cache.clear();
/* remove file */ // remove file
unlink(s->dev->calib_file.c_str()); unlink(dev->calib_file.c_str());
/* signals that sensors will have to be read again */ // signals that sensors will have to be read again
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_FORCE_CALIBRATION:
s->dev->force_calibration = 1;
s->dev->calibration_cache.clear();
s->dev->calib_file.clear();
/* signals that sensors will have to be read again */
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_IGNORE_OFFSETS: {
s->dev->ignore_offsets = true;
break; break;
} }
default: case OPT_FORCE_CALIBRATION: {
DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option); dev->force_calibration = 1;
dev->calibration_cache.clear();
dev->calib_file.clear();
// signals that sensors will have to be read again
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
}
case OPT_IGNORE_OFFSETS: {
dev->ignore_offsets = true;
break;
}
default: {
DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option);
}
} }
} }
@ -6267,13 +6262,13 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
auto* dev = s->dev;
/* don't recompute parameters once data reading is active, ie during scan */ /* don't recompute parameters once data reading is active, ie during scan */
if (!s->dev->read_active) { if (!dev->read_active) {
calc_parameters(s); calc_parameters(s);
} }
if (params) if (params) {
{
*params = s->params; *params = s->params;
/* in the case of a sheetfed scanner, when full height is specified /* in the case of a sheetfed scanner, when full height is specified
@ -6281,11 +6276,11 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params)
* don't know the real document height. * don't know the real document height.
* We don't do that doing buffering image for digital processing * We don't do that doing buffering image for digital processing
*/ */
if (s->dev->model->is_sheetfed && if (dev->model->is_sheetfed &&
s->pos_bottom_right_y == s->opt[OPT_BR_Y].constraint.range->max) s->pos_bottom_right_y == s->opt[OPT_BR_Y].constraint.range->max)
{ {
params->lines = -1; params->lines = -1;
} }
} }
debug_dump(DBG_proc, *params); debug_dump(DBG_proc, *params);
} }
@ -6303,6 +6298,7 @@ void sane_start_impl(SANE_Handle handle)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
auto* dev = s->dev;
if (s->pos_top_left_x >= s->pos_bottom_right_x) { if (s->pos_top_left_x >= s->pos_bottom_right_x) {
throw SaneException("top left x >= bottom right x"); throw SaneException("top left x >= bottom right x");
@ -6312,33 +6308,33 @@ void sane_start_impl(SANE_Handle handle)
} }
// fetch stored calibration // fetch stored calibration
if (s->dev->force_calibration == 0) { if (dev->force_calibration == 0) {
auto path = calibration_filename(s->dev); auto path = calibration_filename(dev);
s->calibration_file = path; s->calibration_file = path;
s->dev->calib_file = path; dev->calib_file = path;
DBG(DBG_info, "%s: Calibration filename set to:\n", __func__); DBG(DBG_info, "%s: Calibration filename set to:\n", __func__);
DBG(DBG_info, "%s: >%s<\n", __func__, s->dev->calib_file.c_str()); DBG(DBG_info, "%s: >%s<\n", __func__, dev->calib_file.c_str());
catch_all_exceptions(__func__, [&]() catch_all_exceptions(__func__, [&]()
{ {
sanei_genesys_read_calibration(s->dev->calibration_cache, s->dev->calib_file); sanei_genesys_read_calibration(dev->calibration_cache, dev->calib_file);
}); });
} }
/* First make sure we have a current parameter set. Some of the // First make sure we have a current parameter set. Some of the
parameters will be overwritten below, but that's OK. */ // parameters will be overwritten below, but that's OK.
calc_parameters(s); calc_parameters(s);
genesys_start_scan(s->dev, s->lamp_off); genesys_start_scan(dev, s->lamp_off);
s->scanning = true; s->scanning = true;
/* allocate intermediate buffer when doing dynamic lineart */ // allocate intermediate buffer when doing dynamic lineart
if (s->dev->settings.scan_mode == ScanColorMode::LINEART) { if (dev->settings.scan_mode == ScanColorMode::LINEART) {
s->dev->binarize_buffer.clear(); dev->binarize_buffer.clear();
s->dev->binarize_buffer.alloc(s->dev->settings.pixels); dev->binarize_buffer.alloc(dev->settings.pixels);
s->dev->local_buffer.clear(); dev->local_buffer.clear();
s->dev->local_buffer.alloc(s->dev->binarize_buffer.size() * 8); dev->local_buffer.alloc(dev->binarize_buffer.size() * 8);
} }
} }
@ -6355,14 +6351,13 @@ void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
Genesys_Device *dev;
size_t local_len; size_t local_len;
if (!s) { if (!s) {
throw SaneException("handle is nullptr"); throw SaneException("handle is nullptr");
} }
dev=s->dev; auto* dev = s->dev;
if (!dev) { if (!dev) {
throw SaneException("dev is nullptr"); throw SaneException("dev is nullptr");
} }
@ -6460,35 +6455,31 @@ void sane_cancel_impl(SANE_Handle handle)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
auto* dev = s->dev;
s->scanning = false; s->scanning = false;
s->dev->read_active = false; dev->read_active = false;
/* no need to end scan if we are parking the head */ // no need to end scan if we are parking the head
if (!s->dev->parking) { if (!dev->parking) {
s->dev->cmd_set->end_scan(s->dev, &s->dev->reg, true); dev->cmd_set->end_scan(dev, &dev->reg, true);
} }
/* park head if flatbed scanner */ // park head if flatbed scanner
if (!s->dev->model->is_sheetfed) { if (!dev->model->is_sheetfed) {
if (!s->dev->parking) { if (!dev->parking) {
s->dev->cmd_set->move_back_home (s->dev, has_flag(s->dev->model->flags, dev->cmd_set->move_back_home(dev, has_flag(dev->model->flags, ModelFlag::MUST_WAIT));
ModelFlag::MUST_WAIT)); dev->parking = !has_flag(dev->model->flags, ModelFlag::MUST_WAIT);
s->dev->parking = !has_flag(s->dev->model->flags, ModelFlag::MUST_WAIT);
} }
} } else {
else // in case of sheetfed scanners, we have to eject the document if still present
{ /* in case of sheetfed scanners, we have to eject the document if still present */ dev->cmd_set->eject_document(dev);
s->dev->cmd_set->eject_document(s->dev);
} }
/* enable power saving mode unless we are parking .... */ // enable power saving mode unless we are parking ....
if (!s->dev->parking) { if (!dev->parking) {
s->dev->cmd_set->save_power(s->dev, true); dev->cmd_set->save_power(dev, true);
} }
return;
} }
SANE_GENESYS_API_LINKAGE SANE_GENESYS_API_LINKAGE