diff options
Diffstat (limited to 'frontend/pisa_view_manager.cc')
-rw-r--r-- | frontend/pisa_view_manager.cc | 1134 |
1 files changed, 1134 insertions, 0 deletions
diff --git a/frontend/pisa_view_manager.cc b/frontend/pisa_view_manager.cc new file mode 100644 index 0000000..ef7a966 --- /dev/null +++ b/frontend/pisa_view_manager.cc @@ -0,0 +1,1134 @@ +/* pisa_view_manager.cc + Copyright (C) 2001, 2004, 2005, 2008, 2009 SEIKO EPSON CORPORATION + + This file is part of the `iscan' program. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + As a special exception, the copyright holders give permission + to link the code of this program with the esmod library and + distribute linked combinations including the two. You must obey + the GNU General Public License in all respects for all of the + code used other then esmod. +*/ + +#include <config.h> + +#include "gettext.h" +#define _(msg_id) gettext (msg_id) + +/*------------------------------------------------------------*/ +#include <gtk/gtk.h> +#ifndef HAVE_GTK_2 +#include <gdk_imlib.h> +#endif +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <regex.h> +#include <dirent.h> +#include <locale.h> +#include <libgen.h> +#include <time.h> + +/*------------------------------------------------------------*/ +#include "pisa_view_manager.h" +#include "pisa_error.h" +#include "pisa_main.h" +#include "pisa_scan_tool.h" +#include "pisa_default_val.h" +#include "pisa_gimp.h" +#include "pisa_aleart_dialog.h" +#include "pisa_change_unit.h" +#include "pisa_preference.h" +#include "pisa_scan_selector.h" + +#include "file-selector.h" + +#include "imgstream.hh" + + +#define DEFAULT_RESOLUTION 300 // dpi + +/*------------------------------------------------------------*/ +view_manager * g_view_manager = 0; + +/*------------------------------------------------------------*/ +int view_manager::create_view_manager ( int argc, char * argv [ ] ) +{ + ::gtk_set_locale ( ); + ::setlocale (LC_NUMERIC, "C"); + ::gtk_init ( & argc, & argv ); + +#ifndef HAVE_GTK_2 + ::gdk_imlib_init ( ); + ::gtk_widget_push_visual ( ::gdk_imlib_get_visual ( ) ); + ::gtk_widget_push_colormap ( ::gdk_imlib_get_colormap ( ) ); +#endif + + try + { + if ( ::g_view_manager ) + throw pisa_error ( PISA_ERR_PARAMETER ); + + ::g_view_manager = new view_manager; + if ( ::g_view_manager == 0 ) + throw pisa_error ( PISA_ERR_OUTOFMEMORY ); + + // initialize parameters + ::g_view_manager->init ( ); + + } + catch ( pisa_error & err ) + { + aleart_dialog aleart_dlg; + + aleart_dlg.message_box ( 0, err.get_error_string ( ) ); + + if ( ::g_view_manager ) + { + delete ::g_view_manager; + ::g_view_manager = 0; + } + + return err.get_error_id ( ); + } + + return PISA_ERR_SUCCESS; +} + +/*------------------------------------------------------------*/ +void view_manager::release_view_manager ( void ) +{ + if ( ::g_view_manager ) + { + delete ::g_view_manager; + ::g_view_manager = 0; + } +} + +/*------------------------------------------------------------*/ +int view_manager::main ( void ) +{ + gtk_main ( ); + + return PISA_ERR_SUCCESS; +} + +/*------------------------------------------------------------*/ +void view_manager::init ( void ) +{ + // initialize + m_scanmanager_cls = 0; + m_main_cls = 0; + m_prev_cls = 0; + m_imgctrl_cls = 0; + m_gamma_cls = 0; + m_config_cls = 0; + m_filsel_cls = 0; + m_scansel_cls = 0; + + // open scanner + m_scanmanager_cls = new scan_manager; + + if ( ! m_scanmanager_cls ) + throw pisa_error ( PISA_ERR_OUTOFMEMORY ); + + open_device ( ); + + m_set.resolution = DEFAULT_RESOLUTION; + m_set.enable_start_button = + m_scanmanager_cls->push_button_needs_polling (); + m_set.enable_draft_mode = false; + m_set.usm = 1; + m_set.unit = PISA_UNIT_INCHES; + + if ( pisa_gimp_plugin ( ) ) + m_set.destination = PISA_DE_GIMP; + else + m_set.destination = PISA_DE_FILE; + + m_main_cls = new main_window; + m_prev_cls = new preview_window; + m_imgctrl_cls = new image_controls; + m_gamma_cls = new gamma_correction; + m_config_cls = new config_window; + m_filsel_cls = new file_selector; + + if ( ! m_main_cls || + ! m_prev_cls || + ! m_imgctrl_cls || + ! m_gamma_cls || + ! m_config_cls || + ! m_filsel_cls ) + { + destroy ( ); + throw ( PISA_ERR_OUTOFMEMORY ); + } + + init_img_info (); + + m_main_cls->init ( ); + m_prev_cls->init ( ); + m_gamma_cls->init ( ); + m_config_cls->init ( ); + m_filsel_cls->init ( ); + + load_preference ( ); + +} + +/*------------------------------------------------------------*/ +void view_manager::destroy ( void ) +{ + save_preference ( ); + + m_set.delete_all ( ); + + if ( m_scanmanager_cls ) + { + try + { + close_device ( ); + } + catch ( pisa_error & err ) + { + aleart_dialog aleart_dlg; + + aleart_dlg.message_box ( 0, err.get_error_string ( ) ); + } + + delete m_scanmanager_cls; + m_scanmanager_cls = 0; + } + + if ( m_main_cls ) + { + delete m_main_cls; + m_main_cls = 0; + } + + if ( m_prev_cls ) + { + delete m_prev_cls; + m_prev_cls = 0; + } + + if ( m_imgctrl_cls ) + { + delete m_imgctrl_cls; + m_imgctrl_cls = 0; + } + + if ( m_gamma_cls ) + { + delete m_gamma_cls; + m_gamma_cls = 0; + } + + if ( m_config_cls ) + { + delete m_config_cls; + m_config_cls = 0; + } + + if ( m_filsel_cls ) + { + delete m_filsel_cls; + m_filsel_cls = 0; + } + + if ( m_scansel_cls ) + { + delete m_scansel_cls; + m_scansel_cls = 0; + } + + ::pisa_quit ( ); +} + +/*------------------------------------------------------------*/ +GtkWidget * view_manager::create_window ( pisa_window_id id ) +{ + GtkWidget * ret = 0; + + switch ( id ) + { + case ID_WINDOW_MAIN: + ret = m_main_cls->create_window ( 0 ); + break; + + case ID_WINDOW_PREV: + ret = m_prev_cls->create_window ( 0 ); + break; + + case ID_WINDOW_CONFIG: + ret = m_config_cls->create_window ( m_main_cls->get_widget ( ) ); + break; + } + + return ret; +} + +/*------------------------------------------------------------*/ +int view_manager::close_window ( pisa_window_id id, int destroy_flag ) +{ + switch ( id ) + { + case ID_WINDOW_MAIN: + m_main_cls->close_window ( destroy_flag ); + destroy ( ); + break; + + case ID_WINDOW_PREV: + m_prev_cls->close_window ( destroy_flag ); + break; + + case ID_WINDOW_CONFIG: + m_config_cls->close_window ( destroy_flag ); + break; + + default: + return PISA_ERR_PARAMETER; + } + + return PISA_ERR_PARAMETER; +} + +image_controls * +view_manager::get_image_controls () +{ + return m_imgctrl_cls; +} + +gamma_correction * +view_manager::get_gamma_correction () +{ + return m_gamma_cls; +} + +/*------------------------------------------------------------*/ +void * view_manager::get_window_cls ( pisa_window_id id ) +{ + void * ret = 0; + + switch ( id ) + { + case ID_WINDOW_MAIN: + ret = m_main_cls; + break; + + case ID_WINDOW_PREV: + ret = m_prev_cls; + break; + + case ID_WINDOW_CONFIG: + ret = m_config_cls; + break; + } + + return ret; +} + +/*------------------------------------------------------------*/ +void view_manager::sensitive ( void ) +{ + int is_img = m_prev_cls->is_prev_img ( ); + + m_main_cls->sensitive ( is_img ); + m_imgctrl_cls->sensitive ( is_img ); + m_gamma_cls->sensitive ( is_img ); + + m_scanmanager_cls->has_prev_img ( is_img ); +} + +/*------------------------------------------------------------*/ +int view_manager::is_gimp ( void ) +{ + return pisa_gimp_plugin ( ); +} + +bool +view_manager::needs_duplex_rotation (void) const +{ + if (!m_scanmanager_cls->using_duplex ()) + return false; + + if (!m_scanmanager_cls->adf_duplex_direction_matches ()) + { // double pass ADF + return m_filsel_cls->has_left_edge_binding (); + } + else + { // single pass ADF + return !m_filsel_cls->has_left_edge_binding (); + } +} + +/*------------------------------------------------------------*/ +void view_manager::start_scan ( void ) +{ + using iscan::file_opener; + using iscan::imgstream; + + if (PISA_ERR_SUCCESS != init_scan_param ()) + return; + + file_opener *fo = NULL; + imgstream *is = NULL; + + bool remove = false; + + // All types of scans need to provide visual feedback on their + // progress and for consecutive scans (via ADF or with the start + // button enabled) it is better to create it here. That way, it + // will not disappear and reappear between calls to scan_file() or + // scan_gimp(), eliminating rather annoying flicker. + _feedback = new progress_window (m_main_cls->get_widget ()); + switch ( m_set.destination ) + { + case PISA_DE_FILE: + { + m_filsel_cls->init (); +#ifndef HAVE_GTK_2 + m_filsel_cls->create_window (m_main_cls->get_widget (), m_set.option, + m_set.enable_start_button, + PISA_PT_BW == m_set.imgtype.pixeltype); +#else + GtkWidget *w = m_main_cls->get_widget (); + m_filsel_cls->create_window (GTK_WINDOW (gtk_widget_get_parent (w)), w, + (m_scanmanager_cls->using_adf () + || m_set.enable_start_button), + m_scanmanager_cls->using_duplex (), + _image_format.c_str ()); +#endif /* HAVE_GTK_2 */ + m_filsel_cls->hide (); + if (!m_filsel_cls->get_pathname ()) // dialog cancelled + break; + + // FIXME: the file_selector (or file name generator) should + // signal a change in file format and all interested + // parties, e.g. an object managing the configuration + // file, should take note and appropriate action + _image_format = m_filsel_cls->get_format_name (); + + if (is_multi_image () + && !m_filsel_cls->multi_page_mode ()) + fo = new file_opener (std::string (m_filsel_cls->get_pathname ()), + m_filsel_cls->get_sequence_number ()); + else + fo = new file_opener (std::string (m_filsel_cls->get_pathname ())); + + try + { + try + { + is = iscan::create_imgstream (*fo, m_filsel_cls->get_type (), + needs_duplex_rotation ()); + } + catch (std::exception& oops) + { + throw pisa_error ( PISA_ERR_OUTOFMEMORY ); + } + } + catch (pisa_error& err) + { + aleart_dialog aleart_dlg; + aleart_dlg.message_box (m_main_cls->get_widget (), + err.get_error_string ()); + m_filsel_cls->destroy (); + remove = true; + break; + } + remove = do_scan (*is, *fo); + m_filsel_cls->destroy (); + } + break; + + case PISA_DE_PRINTER: + { + fo = new file_opener (false); + is = new imgstream (*fo, iscan::PNG); + remove = do_scan (*is, *fo); + } + break; + + case PISA_DE_GIMP: + do_scan_gimp (); + break; + } + delete is; + try + { + if (fo && remove) fo->remove (); + } + catch (std::exception& oops) {} + delete fo; + delete _feedback; + + m_scanmanager_cls->finish_acquire (); +} + +int +view_manager::update_lut (long index) +{ + return update_lut (m_set.get_marquee (index)); +} + +int +view_manager::update_lut (marquee& m) +{ + iscan::build_LUT (m_scanmanager_cls->get_scan_source (), + m_scanmanager_cls->get_film_type (), + m_set, m, !m_scanmanager_cls->has_zoom ()); + + return PISA_ERR_SUCCESS; +} + +bool +view_manager::change_document_source (const imagetype *img_type) +{ + bool success = true; + + try + { + set_image_type (img_type); + m_set.delete_all (); + init_img_info (); // calls m_set.init() + + main_window *main_cls + = static_cast <main_window *> (get_window_cls (ID_WINDOW_MAIN)); + main_cls->enable_start_button (!m_scanmanager_cls->using_adf ()); + } + catch (pisa_error& err) + { + aleart_dialog aleart_dlg; + + aleart_dlg.message_box (m_main_cls->get_widget (), + err.get_error_string ()); + success = false; + } + + set_resolution (DEFAULT_RESOLUTION); + m_gamma_cls->reset (1); + m_prev_cls->resize_window (); + sensitive (); + + return success; +} + +void view_manager::set_device( char * name ) +{ + m_scanmanager_cls->close_device(); + m_scanmanager_cls->open_device( name ); +} + +char * view_manager::get_device_name() const +{ + return m_scansel_cls->get_device( true ); +} + +/*------------------------------------------------------------*/ +void view_manager::open_device ( void ) +{ + sane_init( 0, 0 ); + if (!m_scansel_cls) + m_scansel_cls = new scan_selector( true ); // dialog box + m_scanmanager_cls->open_device ( m_scansel_cls->get_device() ); +} + +/*------------------------------------------------------------*/ +void view_manager::close_device ( void ) +{ + m_scanmanager_cls->close_device ( ); +} + +/*------------------------------------------------------------*/ +void view_manager::load_preference ( void ) +{ + char pref_path [ 256 ]; + char pips_path [ 1024 ] = "lpr"; + char image_format [ 1024 ] = "PNG"; + + cfg_struct cfg [ ] = + { + { "IMG", CFG_STRING, image_format }, + { "PIPS", CFG_STRING, pips_path } + }; + + ::strcpy ( pref_path, ::getenv ( "HOME" ) ); + ::strcat ( pref_path, "/" ); + ::strcat ( pref_path, PREFERENCE ); + + ::get_cfg ( pref_path, cfg, sizeof ( cfg ) / sizeof ( cfg [ 0 ] ) ); + + ::strcpy ( m_config_cls->m_cmd, pips_path ); + _image_format = image_format; +} + +/*------------------------------------------------------------*/ +void view_manager::save_preference ( void ) +{ + char pref_path [ 256 ]; + char pips_path [ 1024 ] = ""; + + cfg_struct cfg [ ] = + { + { "IMG", CFG_STRING, const_cast<char*> (_image_format.c_str ()) }, + { "PIPS", CFG_STRING, pips_path } + }; + + ::strcpy ( pref_path, ::getenv ( "HOME" ) ); + ::strcat ( pref_path, "/" ); + ::strcat ( pref_path, PREFERENCE ); + + ::strcpy ( pips_path, m_config_cls->m_cmd ); + + ::set_cfg ( pref_path, cfg, sizeof ( cfg ) / sizeof ( cfg [ 0 ] ) ); +} + + +int +view_manager::init_img_info (void) +{ + int i; + marquee * marq; + double max_width, max_height; + double coef [ 9 ]; + float brightness, contrast; + long focus; + + + m_scanmanager_cls->set_brightness_method(br_iscan); + m_scanmanager_cls->get_value(SANE_NAME_BRIGHTNESS, &brightness); + m_scanmanager_cls->get_value(SANE_NAME_CONTRAST, &contrast); + + if (m_scanmanager_cls->using_tpu ()) + focus = 25; + else + focus = 0; + + // get max area + m_scanmanager_cls->get_current_max_size ( & max_width, & max_height ); + m_scanmanager_cls->get_color_profile ( coef ); + + // initialize marquee + marq = new marquee ( max_width, max_height, focus, brightness, contrast ); + m_set.init ( & marq ); + + m_set.max_area [ 0 ] = max_width; + m_set.max_area [ 1 ] = max_height; + + for ( i = 0; i < 9; i++ ) + m_set.coef [ i ] = coef [ i ]; + + return PISA_ERR_SUCCESS; +} + +int +view_manager::init_scan_param (void) +{ + marquee marq = get_marquee (m_set.get_marquee_size ( ) - 1); + + pisa_error_id err = m_scanmanager_cls->set_scan_parameters (m_set, marq); + + if (PISA_ERR_SUCCESS != err) + { + aleart_dialog dlg; + + dlg.message_box (m_main_cls->get_widget (), + pisa_error (err).get_error_string ()); + } + return err; +} + +// A pile of status flags used to track what's going on in the scan +// loop. There are probably a few more than really needed, but at +// least these cover the individual situations we can encounter. + +#define SCAN_BUTTON 0x10 +#define SCAN_ADF 0x20 +#define SCAN_NEXT 0x40 +#define SCAN_FINISH 0x80 +#define SCAN_ERROR 0x01 +#define SCAN_CANCEL 0x02 +#define SCAN_SINGLE 0x04 +#define SCAN_DATA 0x08 + +bool +view_manager::do_scan (iscan::imgstream& is, const iscan::file_opener& fo, + bool first_time_around) +{ + static int status; + + if (first_time_around) status = 0; + if (!m_filsel_cls->multi_page_mode ()) status |= SCAN_SINGLE; + if (wait_for_button ()) status |= SCAN_BUTTON | SCAN_NEXT; + if (m_scanmanager_cls->using_adf ()) status |= SCAN_ADF | SCAN_NEXT; + + try + { + do + { + is.next (); + status &= ~SCAN_DATA; + scan_file (is, &status, first_time_around); + first_time_around = false; + if (status & SCAN_ERROR ) status &= ~SCAN_NEXT; + if (status & SCAN_CANCEL) status &= ~SCAN_NEXT; + if (status & SCAN_FINISH) status &= ~SCAN_NEXT; + if ((status & SCAN_DATA) + && !(status & (SCAN_ERROR | SCAN_CANCEL))) + { + is.flush (); + print (fo.name ()); + } + } + while (status & SCAN_NEXT); + } + catch (std::exception& oops) + { + return false; + } + + // Signal whether the file should be removed. Note that ADF and + // scan button based scanning both open a temporary file ahead of + // scanning. Here we signal whether that temporary file needs to + // be removed. Also note that ADF scans ignore the scan button + // setting, so we should check for ADF stuff first. + + if (status & (SCAN_ERROR | SCAN_CANCEL)) return true; + + if (status & SCAN_ADF) + if (status & SCAN_FINISH) return (status & SCAN_SINGLE); + + if (status & SCAN_BUTTON) + if (status & SCAN_FINISH) return (status & SCAN_SINGLE); + + return false; +} + +int +view_manager::do_scan_gimp (bool first_time_around) +{ + int cancel = 0; + + if (!m_scanmanager_cls->using_adf () + && !m_set.enable_start_button) + return scan_gimp (&cancel); + + bool eos = false; + + while (!eos) + { + eos = scan_gimp (&cancel, first_time_around); + first_time_around = false; + } + if (!cancel) + do_scan_gimp (first_time_around); + + return PISA_ERR_SUCCESS; +} + +int +view_manager::dialog_reply( const pisa_error& err ) const +{ + int reply = 0; + + aleart_dialog dlg; + + if ( PISA_STATUS_CANCELLED == err.get_error_id() ) + { + // suppress message box when user cancelled from scanner side + reply = SCAN_ERROR; + } + else if ( ( PISA_STATUS_GOOD < err.get_error_id() ) && + (m_scanmanager_cls->using_adf ()) ) + { + int i = dlg.message_box( m_main_cls->get_widget(), + err.get_error_string(), + _(" Continue "), _(" Cancel ") ); + if (2 == i) + reply = SCAN_FINISH; + else + reply = SCAN_NEXT; + } + else if ( ( PISA_STATUS_GOOD == err.get_error_id() ) && + m_set.enable_start_button ) + { + + int i = dlg.message_box( m_main_cls->get_widget(), + "Waiting for ...", + _(" Finish ") ); + + if ( 1 == i ) + reply = SCAN_FINISH; + } + else + { + dlg.message_box( m_main_cls->get_widget(), + err.get_error_string() ); + + if (PISA_ERR_FILEOPEN != err.get_error_id()) + reply = SCAN_ERROR; + } + + return reply; +} + +/*------------------------------------------------------------*/ +bool +view_manager::scan_gimp (int *cancel, bool first_time_around) +{ + +#ifndef HAVE_ANY_GIMP + + *cancel = 1; // can't scan to GIMP + return true; + +#else + bool error = false; // be optimistic + try + { + *cancel = 0; + + bool reset_params = false; + if (wait_for_button () + && m_scanmanager_cls->is_button_pressed ()) { + // We have an impatient user here who pressed the scanner's + // button *before* we even got a chance to show our WAITING + // message. + m_scanmanager_cls->clear_button_status (); + reset_params = true; + } + + _feedback->set_text (wait_for_button () + ? progress_window::WAITING + : progress_window::WARMING_UP); + _feedback->set_progress (0, 1); + _feedback->show (); + + if (wait_for_button ()) { + long usec = m_scanmanager_cls->get_polling_time (); + while (!m_scanmanager_cls->is_button_pressed () + && !_feedback->is_cancelled ()) { + microsleep (usec); + while (gtk_events_pending ()) { + gtk_main_iteration (); + } + } + if (_feedback->is_cancelled ()) { + *cancel = 1; + return true; + } + if (m_scanmanager_cls->push_button_needs_polling ()) { + m_scanmanager_cls->disable_wait_for_button(); + } + } + + _feedback->set_text (progress_window::WARMING_UP); + + int width, height; + m_scanmanager_cls->init_scan (&width, &height, + first_time_around || reset_params); + + while ( ::gtk_events_pending ( ) ) + ::gtk_main_iteration ( ); + + char depth = 8; + int rowbytes; + switch (m_set.imgtype.pixeltype) + { + case PISA_PT_RGB: + rowbytes = width * 3; + break; + case PISA_PT_GRAY: + rowbytes = width; + break; + case PISA_PT_BW: + depth = 1; + rowbytes = (width + 7) / 8; + break; + default: + rowbytes = 0; + } + + gimp_scan gimp_cls; + if (PISA_ERR_SUCCESS != + gimp_cls.create_gimp_image (width, height, + m_set.imgtype.pixeltype, depth)) + { + m_scanmanager_cls->acquire_image ( 0, 0, 1, 1 ); + + throw pisa_error ( PISA_ERR_OUTOFMEMORY ); + } + + for (int i = 0; i < height; i++) + { + m_scanmanager_cls->acquire_image ( gimp_cls.get_next_buf ( ), + rowbytes, + 1, + *cancel ); + + if ( i == 0 ) + _feedback->set_text (progress_window::SCANNING); + + if (*cancel) + { + error = true; + break; + } + + _feedback->set_progress (i, height); + *cancel = _feedback->is_cancelled (); + + gimp_cls.set_image_rect ( ); + + while ( ::gtk_events_pending ( ) ) + ::gtk_main_iteration ( ); + } + m_scanmanager_cls->acquire_image (0, 1, 1, *cancel); + _feedback->set_progress (height, height); + + gimp_cls.finish_scan ( *cancel ); + } + catch ( pisa_error & err ) + { + error = true; + *cancel = dialog_reply( err ); + } + + m_scanmanager_cls->release_memory (); + + return error; +#endif // HAVE_ANY_GIMP +} + +void +view_manager::scan_file (iscan::imgstream& is, int *status, + bool first_time_around) +{ + try + { + bool reset_params = false; + if (wait_for_button () + && m_scanmanager_cls->is_button_pressed ()) { + // We have an impatient user here who pressed the scanner's + // button *before* we even got a chance to show our WAITING + // message. + m_scanmanager_cls->clear_button_status (); + reset_params = true; + } + + _feedback->set_text (wait_for_button () + ? progress_window::WAITING + : progress_window::WARMING_UP); + _feedback->set_progress (0, 1); + _feedback->show (); + + while (::gtk_events_pending()) + ::gtk_main_iteration(); + + if (wait_for_button ()) { + long usec = m_scanmanager_cls->get_polling_time (); + while (!m_scanmanager_cls->is_button_pressed () + && !_feedback->is_cancelled ()) { + microsleep (usec); + while (gtk_events_pending ()) { + gtk_main_iteration (); + } + } + if (_feedback->is_cancelled ()) { + // user clicked the Finish button! + *status |= SCAN_FINISH; + *status &= ~SCAN_NEXT; + return; + } + if (m_scanmanager_cls->push_button_needs_polling ()) { + m_scanmanager_cls->disable_wait_for_button(); + } + } + + _feedback->set_text (progress_window::WARMING_UP); + + int width, height; + m_scanmanager_cls->init_scan (&width, &height, + first_time_around || reset_params); + + while (::gtk_events_pending()) + ::gtk_main_iteration(); + + int rowbytes; + iscan::colour_space cs; + + switch (m_set.imgtype.pixeltype) + { + case PISA_PT_RGB: + rowbytes = width * 3; + cs = iscan::RGB; + break; + case PISA_PT_GRAY: + rowbytes = width; + cs = iscan::gray; + break; + case PISA_PT_BW: + rowbytes = (width + 7) / 8; + cs = iscan::mono; + break; + default: + rowbytes = 0; + throw pisa_error (PISA_ERR_PARAMETER); + } + + try + { + is.size (width, height); + is.depth (PISA_PT_BW == m_set.imgtype.pixeltype ? 1 : 8); + is.colour (cs); + is.resolution (m_set.resolution, m_set.resolution); + } + catch (pisa_error& oops) + { + m_scanmanager_cls->acquire_image( 0, 0, 1, 1 ); + throw oops; + } + + unsigned char *img = new unsigned char[rowbytes]; + for (int i = 0; i < height; ++i) + { + m_scanmanager_cls->acquire_image (img, rowbytes, 1, + *status & SCAN_CANCEL); + + if (0 == i) + _feedback->set_text (progress_window::SCANNING); + + if (*status & SCAN_CANCEL) + { + //error = true; + break; + } + + _feedback->set_progress (i, height); + if (_feedback->is_cancelled ()) + *status |= SCAN_CANCEL; + + try + { + try + { + is.write ((const char *)img, rowbytes); + *status |= SCAN_DATA; + } + catch (std::exception& oops) + { // map to old API and rethrow + throw (pisa_error (PISA_ERR_OUTOFMEMORY)); + } + } + catch (pisa_error& oops) + { + *status |= SCAN_CANCEL; + + if (i < height) + m_scanmanager_cls->acquire_image (img, rowbytes, 1, + *status & SCAN_CANCEL); + aleart_dialog aleart_dlg; + aleart_dlg.message_box( m_main_cls->get_widget(), + oops.get_error_string() ); + break; + } + while (::gtk_events_pending()) + ::gtk_main_iteration(); + } + delete[] img; + + m_scanmanager_cls->acquire_image (0, 1, 1, *status & SCAN_CANCEL); + _feedback->set_progress (height, height); + } + catch (pisa_error& oops) + { + //error = true; + *status |= dialog_reply (oops); + } + + m_scanmanager_cls->release_memory (); + + while (::gtk_events_pending()) + ::gtk_main_iteration(); + + return; +} + +void +view_manager::print (const std::string& filename) const +{ + if (PISA_DE_PRINTER == m_set.destination) + { + char cmd[1024]; // FIXME: buffer overflow! + sprintf (cmd, "%s %s", m_config_cls->m_cmd, filename.c_str ()); + system (cmd); // FIXME: check cmd exit status + + while (gtk_events_pending ()) gtk_main_iteration (); + + remove (filename.c_str ()); + } +} + +bool +view_manager::is_multi_image (void) const +{ + return (m_scanmanager_cls->using_adf () || m_set.enable_start_button); +} + +bool +view_manager::wait_for_button (void) const +{ + if (m_scanmanager_cls->push_button_needs_polling ()) + { + return (m_set.enable_start_button); + } + else + { + return (m_set.enable_start_button && !m_scanmanager_cls->using_adf ()); + } +} + +void +view_manager::set_resolution (long resolution) +{ + long adjust_res[2] = {resolution, resolution}; + + m_set.resolution = resolution; + + /* set resolution to backend */ + m_scanmanager_cls->get_valid_resolution (&adjust_res[0], &adjust_res[1], true); + m_scanmanager_cls->set_scan_resolution (adjust_res[0], adjust_res[1]); +} + +void +view_manager::set_image_type (const imagetype *type) +{ + memcpy (&m_set.imgtype, type, sizeof (imagetype)); + m_scanmanager_cls->set_color_mode(type->pixeltype, type->bitdepth); +} + +int +view_manager::microsleep (size_t usec) +{ + struct timespec ts; + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + + return nanosleep (&ts, NULL); +} |