Compare commits
2 Commits
a2681d2a22
...
df8c4042c4
Author | SHA1 | Date | |
---|---|---|---|
df8c4042c4 | |||
8a7940bfbb |
60
xsanecli.py
60
xsanecli.py
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# GIMP 3.0 plug-in for scanning via XSane
|
# GIMP 3.0 plug-in for scanning via XSane
|
||||||
# Copyright (C) 2024 Lee Yingtong Li (RunasSudo)
|
# Copyright (C) 2024-2025 Lee Yingtong Li (RunasSudo)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -28,36 +28,54 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
DEVICE_NAME = None # e.g. DEVICE_NAME = 'escl:http://10.0.0.1:80'
|
DEVICE_NAME = None # e.g. DEVICE_NAME = 'escl:http://10.0.0.1:80'
|
||||||
|
SCAN_MULTIPLE = True
|
||||||
|
|
||||||
def xsanecli_run(procedure, config, run_data, *args):
|
def xsanecli_run(procedure, config, run_data, *args):
|
||||||
# Get temporary directory
|
# Get temporary directory
|
||||||
tempdir = tempfile.mkdtemp('gimp-plugin-xsanecli')
|
tempdir = tempfile.mkdtemp('gimp-plugin-xsanecli')
|
||||||
png_out = os.path.join(tempdir, 'out.png')
|
png_out = os.path.join(tempdir, 'out.png')
|
||||||
|
|
||||||
|
xsane_env = dict(os.environb)
|
||||||
|
|
||||||
|
# Fix if DISPLAY is set to a Wayland display
|
||||||
|
# For some reason, in Wayland contexts, DISPLAY is clobbered with WAYLAND_DISPLAY when Python is called
|
||||||
|
# This causes "Gtk-WARNING: cannot open display: wayland-0"
|
||||||
|
if b'DISPLAY' in xsane_env and xsane_env[b'DISPLAY'].startswith(b'wayland-'):
|
||||||
|
# Recover the original environment from GIMP (the parent process)
|
||||||
|
with open('/proc/{}/environ'.format(os.getppid()), 'rb') as f:
|
||||||
|
orig_env = {var[:var.index(b'=')]: var[var.index(b'=')+1:] for var in f.read().split(b'\0') if var}
|
||||||
|
|
||||||
|
if b'DISPLAY' in orig_env:
|
||||||
|
xsane_env[b'DISPLAY'] = orig_env[b'DISPLAY']
|
||||||
|
|
||||||
# Open XSane
|
# Open XSane
|
||||||
args = ['xsane', '--save', '--no-mode-selection', '--force-filename', png_out, '--print-filenames'] + ([DEVICE_NAME] if DEVICE_NAME else [])
|
args = ['xsane', '--save', '--no-mode-selection', '--force-filename', png_out, '--print-filenames'] + ([DEVICE_NAME] if DEVICE_NAME else [])
|
||||||
proc = subprocess.Popen(args, stdout=subprocess.PIPE, encoding='utf-8')
|
proc = subprocess.Popen(args, stdout=subprocess.PIPE, encoding='utf-8', env=xsane_env)
|
||||||
|
|
||||||
# Wait until XSane prints the name of the scanned file, indicating scanning is finished
|
while True:
|
||||||
# This blocks Python but that is ok because GIMP UI is not affected
|
# Wait until XSane prints the name of the scanned file, indicating scanning is finished
|
||||||
result = proc.stdout.readline().strip()
|
# This blocks Python but that is ok because GIMP UI is not affected
|
||||||
|
result = proc.stdout.readline().strip()
|
||||||
|
|
||||||
|
if result == '':
|
||||||
|
# XSane was closed
|
||||||
|
break
|
||||||
|
|
||||||
|
if result != 'XSANE_IMAGE_FILENAME: ' + png_out:
|
||||||
|
Gimp.message('Unexpected XSane result')
|
||||||
|
return Gimp.ValueArray.new_from_values([GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.EXECUTION_ERROR)])
|
||||||
|
|
||||||
|
# Open image
|
||||||
|
image = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE, Gio.File.new_for_path(png_out))
|
||||||
|
Gimp.Display.new(image)
|
||||||
|
|
||||||
|
# Remove temporary files
|
||||||
|
os.unlink(png_out)
|
||||||
|
|
||||||
|
if not SCAN_MULTIPLE:
|
||||||
|
proc.terminate()
|
||||||
|
break
|
||||||
|
|
||||||
proc.terminate()
|
|
||||||
|
|
||||||
if result == '':
|
|
||||||
# XSane was closed
|
|
||||||
return Gimp.ValueArray.new_from_values([GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.CANCEL)])
|
|
||||||
|
|
||||||
if result != 'XSANE_IMAGE_FILENAME: ' + png_out:
|
|
||||||
Gimp.message('Unexpected XSane result')
|
|
||||||
return Gimp.ValueArray.new_from_values([GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.EXECUTION_ERROR)])
|
|
||||||
|
|
||||||
# Open image
|
|
||||||
image = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE, Gio.File.new_for_path(png_out))
|
|
||||||
Gimp.Display.new(image)
|
|
||||||
|
|
||||||
# Remove temporary files
|
|
||||||
os.unlink(png_out)
|
|
||||||
os.rmdir(tempdir)
|
os.rmdir(tempdir)
|
||||||
|
|
||||||
return Gimp.ValueArray.new_from_values([GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.SUCCESS), GObject.Value(Gimp.Image.__gtype__, image)])
|
return Gimp.ValueArray.new_from_values([GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.SUCCESS), GObject.Value(Gimp.Image.__gtype__, image)])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user