Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Silbe <sascha-pgp@silbe.org>2012-08-14 09:05:31 (GMT)
committer Sascha Silbe <sascha-pgp@silbe.org>2012-08-14 09:12:35 (GMT)
commit77315c7d10dc06008ca80e67fe22a9ba279c5df4 (patch)
treefbabe6eeb5b085af5a560aba66d517ea83646347
parentde41bbd42ff2f45f2be9c17991e1e018ec05abd7 (diff)
Use the same scanner device again when resuming
Save the scanner device in-use at the time of closing and try to open the same device again when resuming the session. Connecting new devices supported by SANE (e.g. webcams) won't cause the wrong device to be picked anymore. Also lays the foundation for letting the user change the scanner device during the session.
-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: