Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/scan.py
diff options
context:
space:
mode:
Diffstat (limited to 'scan.py')
-rw-r--r--scan.py120
1 files changed, 80 insertions, 40 deletions
diff --git a/scan.py b/scan.py
index 7c779c8..3840180 100644
--- a/scan.py
+++ b/scan.py
@@ -64,7 +64,7 @@ class SettingsToolbar(gtk.ToolPalette):
def set_scanner(self, scanner):
self._scanner = scanner
self._clear()
- if self._scanner:
+ if self._scanner is not None:
self._add_options()
def _clear(self):
@@ -286,9 +286,9 @@ class SettingsToolbar(gtk.ToolPalette):
class ScanThread(threading.Thread):
- def __init__(self, devs, temp_dir, callback=None):
+ def __init__(self, temp_dir, callback=None):
threading.Thread.__init__(self)
- self._devs = devs
+ self._device = None
self._temp_dir = temp_dir
self._callback = callback
self._cond = threading.Condition()
@@ -298,6 +298,10 @@ class ScanThread(threading.Thread):
self._ready = False
self._dpi = None
+ def set_device(self, device):
+ with self._cond:
+ self._device = device
+
def run(self):
while True:
with self._cond:
@@ -323,6 +327,9 @@ class ScanThread(threading.Thread):
@trace()
def start_scan(self):
with self._cond:
+ if self._device is None:
+ raise ValueError('No device set')
+
logging.debug('start_scan(): got lock')
self._action = 'start'
self._cond.notify()
@@ -358,8 +365,8 @@ class ScanThread(threading.Thread):
self._images = None
self._error = None
- source = getattr(self._devs[0], 'source', 'Auto')
- if getattr(self._devs[0], 'batch_scan', False):
+ source = getattr(self._device, 'source', 'Auto')
+ if getattr(self._device, 'batch_scan', False):
scan_multi = source in ['Auto', 'ADF']
else:
scan_multi = source == 'ADF'
@@ -369,8 +376,8 @@ class ScanThread(threading.Thread):
self._scan_multi()
else:
logging.debug('starting single scan')
- self._dpi = self._devs[0].resolution
- self._images = [self._process_image(self._devs[0].scan())]
+ self._dpi = self._device.resolution
+ self._images = [self._process_image(self._device.scan())]
except sane.error, exc:
# Ouch. sane.error doesn't derive from Exception :-/
@@ -391,18 +398,18 @@ class ScanThread(threading.Thread):
@trace()
def _scan_multi(self):
logging.debug('_scan: calling multi_scan()')
- scan_iter = self._devs[0].multi_scan()
+ scan_iter = self._device.multi_scan()
logging.debug('_scan: acquiring images')
images = []
try:
- self._dpi = self._devs[0].resolution
+ self._dpi = self._device.resolution
for image in scan_iter:
images.append(self._process_image(image))
if self._check_action(['stop', 'quit']):
break
- self._dpi = self._devs[0].resolution
+ self._dpi = self._device.resolution
self._images = images
@@ -480,8 +487,10 @@ class ScanActivity(activity.Activity):
def __init__(self, handle):
activity.Activity.__init__(self, handle)
self.max_participants = 1
- self._scanner_name = None
- self._scanners = []
+ # content: (device_name, vendor, model, description)
+ self._scanner_infos = []
+ self._current_scanner = None
+ self._current_scanner_name = None
self._scanner_options = {'source': 'ADF'}
self._status = 'init'
self._msg_box_buf = None
@@ -489,10 +498,12 @@ class ScanActivity(activity.Activity):
self._scan_button = None
self._settings_toolbar = None
temp_dir = os.path.join(self.get_activity_root(), 'tmp')
- self._scan_thread = ScanThread(self._scanners, temp_dir,
+ self._scan_thread = ScanThread(temp_dir,
callback=self._scan_finished_cb)
self._scan_thread.start()
self._setup_widgets()
+ # TODO: delay opening scanner device if we're resuming a
+ # previous session
self._init_scanner()
@trace()
@@ -504,47 +515,62 @@ class ScanActivity(activity.Activity):
activity.Activity.destroy(self)
def read_file(self, file_path):
- if not self._scanners:
+ if not self._scanner_infos:
+ # no scanners available, nothing to do for now (see TODO
+ # item in write_file())
return
globals_dict = {'__builtins__': None}
settings = eval(file(file_path).read(), globals_dict)
+ logging.debug('old settings: %r', settings)
+ scanner_name = settings.pop('_scanner_name', None)
+ if not scanner_name:
+ # Saved by a previous version, just pick the first
+ # available scanner like the previous version did.
+ scanner_name = self._scanner_infos[0][0]
+
+ if scanner_name not in [info[0] for info in self._scanner_infos]:
+ # The previous scanner is not available right now, pick
+ # another one and apply as much of the previous settings
+ # as we can.
+ scanner_name = self._scanner_infos[0][0]
+
+ self._open_scanner(scanner_name)
self._set_settings(settings)
- # TODO: don't call set_scanner() twice when resuming (once in
- # _init_scanner() and once here)
- self._settings_toolbar.set_scanner(self._scanners[0])
+ # HACK: cause the toolbar to re-read the settings after
+ # changing them
+ self._settings_toolbar.set_scanner(self._current_scanner)
def write_file(self, file_path):
+ # TODO: retain settings for all scanners, not just the current one
self.metadata['mime_type'] = 'text/plain'
with file(file_path, 'w') as f:
f.write(repr(self._get_settings()))
@trace()
def _get_settings(self):
- if not self._scanners:
+ if self._current_scanner is None:
return {}
- settings = {}
- scanner = self._scanners[0]
- for py_name in scanner.optlist:
+ settings = {'_scanner_name': self._current_scanner_name}
+ for py_name in self._current_scanner.optlist:
logging.debug('getting value for setting %r', py_name)
- option = scanner[py_name]
+ option = self._current_scanner[py_name]
if option.type in [sane.TYPE_BOOL, sane.TYPE_INT,
sane.TYPE_FIXED, sane.TYPE_STRING] and option.is_active():
- settings[py_name] = getattr(scanner, py_name)
+ settings[py_name] = getattr(self._current_scanner, py_name)
return settings
@trace()
def _set_settings(self, settings):
- if not self._scanners:
+ if self._current_scanner is None:
return
- scanner = self._scanners[0]
for name, value in settings.items():
try:
- setattr(scanner, name, value)
+ setattr(self._current_scanner, name, value)
except AttributeError:
logging.info('Saved setting %r=%r not support by current'
@@ -557,41 +583,55 @@ class ScanActivity(activity.Activity):
@trace()
def _init_scanner(self):
sane.init()
- scanner_devs = sane.get_devices()
- if not scanner_devs:
+ self._scanner_infos = sane.get_devices()
+ if not self._scanner_infos:
self._set_status('no-dev')
return
- self._scanner_name = scanner_devs[0][0]
- self._reopen_scanner()
+ self._open_scanner(self._scanner_infos[0][0])
+
+ def _open_scanner(self, name):
+ """Open the current scanner device
- def _reopen_scanner(self):
- """Reopen scanner device to work around lower layer bugs."""
- if self._scanners:
+ Close the previous device if there is one, but ignore errors
+ while closing. Open the device identified by name.
+
+ Can be used to open the scanner device on start-up, change the
+ current scanner or reopen the scanner device to work around
+ lower layer bugs.
+ """
+ if self._current_scanner:
+ old_scanner, self._current_scanner = self._current_scanner, None
try:
- old_scanner = self._scanners.pop()
old_scanner.close()
del old_scanner
except sane.error, exc:
logging.exception('Error closing scanner')
- if not self._scanner_name:
+ if not name:
self._set_status('no-dev')
+ self._set_scanner(None, None)
return
try:
- self._scanners.append(sane.open(self._scanner_name))
+ scanner = sane.open(name)
except sane.error, exc:
- logging.exception('Error opening scanner %r', self._scanner_name)
+ logging.exception('Error opening scanner %r', name)
self._show_error(exc)
return
- self._settings_toolbar.set_scanner(self._scanners[0])
-
+ self._set_scanner(scanner, name)
self._set_status('ready')
+ @trace()
+ def _set_scanner(self, device, name):
+ self._current_scanner = device
+ self._current_scanner_name = name
+ self._scan_thread.set_device(device)
+ self._settings_toolbar.set_scanner(device)
+
def _setup_widgets(self):
self._setup_toolbar()
self._setup_canvas()
@@ -755,7 +795,7 @@ class ScanActivity(activity.Activity):
if not exc:
self._set_status('ready')
else:
- self._reopen_scanner()
+ self._open_scanner(self._current_scanner_name)
def _add_images(self, image_infos):
for info in image_infos: