Holger Hans Peter Freyther has proposed merging lp:~holger+lp/simple-scan/simple-scan-cli into lp:simple-scan.
Requested reviews: Simple Scan Development Team (simple-scan-team) For more details, see: https://code.launchpad.net/~holger+lp/simple-scan/simple-scan-cli/+merge/91558 I was not able to find a tool that can scan to a PDF from cli (scanimage does not support it). I hacked this together, it hardcodes a lot (A4, DPI, scan mode), I messed up the author and (bzr rewrite has no interactive mode that would allow me to fix it). Right now the question is if you would do: 1.) Build a libsimplescan and install it (.vapi file so I could build my cli with that) 2.) Include a cli directly -- https://code.launchpad.net/~holger+lp/simple-scan/simple-scan-cli/+merge/91558 Your team Simple Scan Development Team is requested to review the proposed merge of lp:~holger+lp/simple-scan/simple-scan-cli into lp:simple-scan.
=== modified file '.bzrignore' --- .bzrignore 2011-06-12 10:13:06 +0000 +++ .bzrignore 2012-02-04 17:34:18 +0000 @@ -32,3 +32,10 @@ src/scanner.c src/simple-scan.c src/ui.c +src/simple-scan-cli.c +src/libsimplescan_a_vala.stamp +src/simple-scan-cli +src/simple-scan.h +src/simple-scan.vapi +src/simple_scan_cli_vala.stamp + === modified file 'configure.ac' --- configure.ac 2011-12-08 04:37:24 +0000 +++ configure.ac 2012-02-04 17:34:18 +0000 @@ -11,6 +11,7 @@ AM_PROG_VALAC([0.13.0]) AM_PROG_CC_C_O AC_HEADER_STDC +AC_PROG_RANLIB GLIB_GSETTINGS === modified file 'src/Makefile.am' --- src/Makefile.am 2011-07-10 06:59:21 +0000 +++ src/Makefile.am 2012-02-04 17:34:18 +0000 @@ -1,6 +1,7 @@ -bin_PROGRAMS = simple-scan +bin_PROGRAMS = simple-scan simple-scan-cli +noinst_LIBRARIES = libsimplescan.a -simple_scan_SOURCES = \ +libsimplescan_a_SOURCES = \ config.vapi \ book.vala \ book-view.vala \ @@ -9,21 +10,38 @@ page.vala \ page-view.vala \ sane.vapi \ + scanner.vala + +libsimplescan_a_VALAFLAGS = --library simple-scan -H simple-scan.h + +BUILT_SOURCES = simple-scan.vapi + +simple-scan.vapi: libsimplescan.a + +simple_scan_SOURCES = \ + config.vapi \ + sane.vapi \ + simple-scan.vapi \ simple-scan.vala \ - scanner.vala \ ui.vala -simple_scan_VALAFLAGS = \ +simple_scan_cli_SOURCES = \ + config.vapi \ + sane.vapi \ + simple-scan.vapi \ + simple-scan-cli.vala + +VALAFLAGS = \ --pkg=zlib \ --pkg=gudev-1.0 \ --pkg=gio-2.0 \ --pkg=gtk+-3.0 if HAVE_COLORD -simple_scan_VALAFLAGS += -D HAVE_COLORD +VALAFLAGS += -D HAVE_COLORD endif -simple_scan_CFLAGS = \ +AM_CFLAGS = \ $(SIMPLE_SCAN_CFLAGS) \ $(COLORD_CFLAGS) \ $(WARN_CFLAGS) \ @@ -38,13 +56,23 @@ simple_scan_LDADD = \ $(SIMPLE_SCAN_LIBS) \ $(COLORD_LIBS) \ + libsimplescan.a \ + -lsane \ + -ljpeg \ + -lm + +simple_scan_cli_LDADD = \ + $(SIMPLE_SCAN_LIBS) \ + $(COLORD_LIBS) \ + libsimplescan.a \ -lsane \ -ljpeg \ -lm CLEANFILES = \ $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \ - *_vala.stamp + *_vala.stamp \ + simple-scan.vapi DISTCLEANFILES = \ Makefile.in === added file 'src/simple-scan-cli.vala' --- src/simple-scan-cli.vala 1970-01-01 00:00:00 +0000 +++ src/simple-scan-cli.vala 2012-02-04 17:34:18 +0000 @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <[email protected]> + * + * 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 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public class Application +{ + static bool show_version; + static bool debug_enabled; + static string? output_name; + public static const OptionEntry[] options = + { + { "version", 'v', 0, OptionArg.NONE, ref show_version, + /* Help string for command line --version flag */ + N_("Show release version"), null}, + { "debug", 'd', 0, OptionArg.NONE, ref debug_enabled, + /* Help string for command line --debug flag */ + N_("Print debugging messages"), null}, + { "output", 'o', 0, OptionArg.STRING, ref output_name, + /* Help string for --output */ + N_("Store the PDF to this file"), null}, + { null } + }; + private static Timer log_timer; + private static FileStream? log_file; + + private ScanDevice? default_device = null; + private bool have_devices = false; + private GUdev.Client udev_client; + private Scanner scanner; + private Book book; + private GLib.MainLoop loop = new MainLoop (); + + private void initialize_book () + { + book = new Book (); + book.append_page (1260, 1771, + 150, + ScanDirection.BOTTOM_TO_TOP); + } + + public Application (ScanDevice? device = null) + { + default_device = device; + + initialize_book (); + + scanner = Scanner.get_instance (); + scanner.update_devices.connect (update_scan_devices_cb); + scanner.request_authorization.connect (authorize_cb); + scanner.expect_page.connect (scanner_new_page_cb); + scanner.got_page_info.connect (scanner_page_info_cb); + scanner.got_line.connect (scanner_line_cb); + scanner.page_done.connect (scanner_page_done_cb); + scanner.document_done.connect (scanner_document_done_cb); + scanner.scan_failed.connect (scanner_failed_cb); + scanner.scanning_changed.connect (scanner_scanning_changed_cb); + + string[]? subsystems = { "usb", null }; + udev_client = new GUdev.Client (subsystems); + udev_client.uevent.connect (on_uevent); + + if (default_device != null) + { + List<ScanDevice> device_list = null; + + device_list.append (default_device); + } + } + + public void start () + { + stdout.printf(_("Starting simple-scan cli.\n")); + scanner.start (); + } + + public void run () + { + loop.run (); + } + + private void update_scan_devices_cb (Scanner scanner, List<ScanDevice> devices) + { + var devices_copy = devices.copy (); + + /* If the default device is not detected add it to the list */ + if (default_device != null) + { + var default_in_list = false; + foreach (var device in devices_copy) + { + if (device.name == default_device.name) + { + default_in_list = true; + break; + } + } + + if (!default_in_list) + devices_copy.prepend (default_device); + } + + have_devices = devices_copy.length () > 0; + //ui.set_scan_devices (devices_copy); + + stdout.printf("Found scan devices. Starting\n"); + scan (); + } + + private void authorize_cb (Scanner scanner, string resource) + { + stderr.printf ("Authorization not implemented.\n"); + //string username, password; + //scanner.authorize (username, password); + } + + private Page append_page () + { + /* Use current page if not used */ + var page = book.get_page (-1); + if (page != null && !page.has_data ()) + { + page.start (); + return page; + } + + /* Copy info from previous page */ + var scan_direction = ScanDirection.TOP_TO_BOTTOM; + bool do_crop = false; + string named_crop = null; + var width = 100, height = 100, dpi = 100, cx = 0, cy = 0, cw = 0, ch = 0; + if (page != null) + { + scan_direction = page.get_scan_direction (); + width = page.get_width (); + height = page.get_height (); + dpi = page.get_dpi (); + + do_crop = page.has_crop (); + if (do_crop) + { + named_crop = page.get_named_crop (); + page.get_crop (out cx, out cy, out cw, out ch); + } + } + + page = book.append_page (width, height, dpi, scan_direction); + if (do_crop) + { + if (named_crop != null) + { + page.set_named_crop (named_crop); + } + else + page.set_custom_crop (cw, ch); + page.move_crop (cx, cy); + } + page.start (); + + return page; + } + + public void scan () + { + stdout.printf("Going to scan a page.\n"); + if (!scanner.is_scanning ()) + append_page(); + + var options = new ScanOptions (); + options.type = ScanType.SINGLE; + options.scan_mode = ScanMode.LINEART; + options.dpi = 150; + options.depth = 2; + options.paper_width = 0; + options.paper_height = 0; + scanner.scan(null, options); + } + + private void scanner_new_page_cb (Scanner scanner) + { + append_page (); + } + + private string? get_profile_for_device (string device_name) + { +#if HAVE_COLORD + var device_id = "sane:%s".printf (device_name); + debug ("Getting color profile for device %s", device_name); + + var client = new Colord.Client (); + try + { + client.connect_sync (); + } + catch (Error e) + { + debug ("Failed to connect to colord: %s", e.message); + return null; + } + + Colord.Device device; + try + { + device = client.find_device_by_property_sync (Colord.DEVICE_PROPERTY_SERIAL, device_id); + } + catch (Error e) + { + debug ("Unable to find colord device %s: %s", device_name, e.message); + return null; + } + + try + { + device.connect_sync (); + } + catch (Error e) + { + debug ("Failed to get properties from the device %s: %s", device_name, e.message); + return null; + } + + var profile = device.get_default_profile (); + if (profile == null) + { + debug ("No default color profile for device: %s", device_name); + return null; + } + + try + { + profile.connect_sync (); + } + catch (Error e) + { + debug ("Failed to get properties from the profile %s: %s", device_name, e.message); + return null; + } + + if (profile.filename == null) + { + debug ("No icc color profile for the device %s", device_name); + return null; + } + + debug ("Using color profile %s for device %s", profile.filename, device_name); + return profile.filename; +#else + return null; +#endif + } + + private void scanner_page_info_cb (Scanner scanner, ScanPageInfo info) + { + debug ("Page is %d pixels wide, %d pixels high, %d bits per pixel", + info.width, info.height, info.depth); + + /* Add a new page */ + var page = append_page (); + page.set_page_info (info); + + /* Get ICC color profile */ + /* FIXME: The ICC profile could change */ + /* FIXME: Don't do a D-bus call for each page, cache color profiles */ + page.set_color_profile (get_profile_for_device (info.device)); + } + + private void scanner_line_cb (Scanner scanner, ScanLine line) + { + var page = book.get_page ((int) book.get_n_pages () - 1); + page.parse_scan_line (line); + } + + private void scanner_page_done_cb (Scanner scanner) + { + var page = book.get_page ((int) book.get_n_pages () - 1); + page.finish (); + + stdout.printf("Finished a page.\n"); + book.save("pdf", File.new_for_path(output_name)); + quit(); + } + + private void remove_empty_page () + { + var page = book.get_page ((int) book.get_n_pages () - 1); + + /* Remove a failed page */ + if (page.has_data ()) + page.finish (); + else + book.delete_page (page); + } + + private void scanner_document_done_cb (Scanner scanner) + { + remove_empty_page (); + } + + private void scanner_failed_cb (Scanner scanner, int error_code, string error_string) + { + remove_empty_page (); + if (error_code != Sane.Status.CANCELLED) + { + stderr.printf("%s: %s\n", _("Failed to scan"), error_string); + } + } + + private void scanner_scanning_changed_cb (Scanner scanner) + { + } + + private void quit() + { + book = null; + udev_client = null; + scanner.free (); + + stdout.printf("Quit...\n"); + loop.quit (); + } + + private static void log_cb (string? log_domain, LogLevelFlags log_level, string message) + { + /* Log everything to a file */ + if (log_file != null) + { + string prefix; + + switch (log_level & LogLevelFlags.LEVEL_MASK) + { + case LogLevelFlags.LEVEL_ERROR: + prefix = "ERROR:"; + break; + case LogLevelFlags.LEVEL_CRITICAL: + prefix = "CRITICAL:"; + break; + case LogLevelFlags.LEVEL_WARNING: + prefix = "WARNING:"; + break; + case LogLevelFlags.LEVEL_MESSAGE: + prefix = "MESSAGE:"; + break; + case LogLevelFlags.LEVEL_INFO: + prefix = "INFO:"; + break; + case LogLevelFlags.LEVEL_DEBUG: + prefix = "DEBUG:"; + break; + default: + prefix = "LOG:"; + break; + } + + log_file.printf ("[%+.2fs] %s %s\n", log_timer.elapsed (), prefix, message); + } + + /* Only show debug if requested */ + if ((log_level & LogLevelFlags.LEVEL_DEBUG) != 0) + { + if (debug_enabled) + Log.default_handler (log_domain, log_level, message); + } + else + Log.default_handler (log_domain, log_level, message); + } + + private void on_uevent (GUdev.Client client, string action, GUdev.Device device) + { + scanner.redetect (); + } + + public static int main (string[] args) + { + Intl.setlocale (LocaleCategory.ALL, ""); + Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALE_DIR); + Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8"); + Intl.textdomain (Config.GETTEXT_PACKAGE); + + var c = new OptionContext (/* Arguments and description for --help text */ + _("[DEVICE...] - Scanning utility")); + c.add_main_entries (options, Config.GETTEXT_PACKAGE); + try + { + c.parse (ref args); + } + catch (Error e) + { + stderr.printf ("%s\n", e.message); + stderr.printf (/* Text printed out when an unknown command-line argument provided */ + _("Run '%s --help' to see a full list of available command line options."), args[0]); + stderr.printf ("\n"); + return Posix.EXIT_FAILURE; + } + if (show_version) + { + /* Note, not translated so can be easily parsed */ + stderr.printf ("simple-scan-cli %s\n", Config.VERSION); + return Posix.EXIT_SUCCESS; + } + + ScanDevice? device = null; + if (args.length > 1) + { + device = new ScanDevice (); + device.name = args[1]; + device.label = args[1]; + } + + + /* Log to a file */ + log_timer = new Timer (); + var path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", null); + DirUtils.create_with_parents (path, 0700); + path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", "simple-scan-cli.log", null); + log_file = FileStream.open (path, "w"); + Log.set_default_handler (log_cb); + + debug ("Starting Simple Scan CLI %s, PID=%i", Config.VERSION, Posix.getpid ()); + + Application app = new Application (device); + app.start (); + app.run (); + + return Posix.EXIT_SUCCESS; + } +} === modified file 'src/ui.vala' --- src/ui.vala 2011-12-08 04:37:24 +0000 +++ src/ui.vala 2012-02-04 17:34:18 +0000 @@ -652,7 +652,7 @@ var options = new ScanOptions (); if (document_hint == "text") { - options.scan_mode = ScanMode.GRAY; + options.scan_mode = ScanMode.LINEART; options.dpi = get_text_dpi (); options.depth = 2; }
_______________________________________________ Mailing list: https://launchpad.net/~simple-scan-team Post to : [email protected] Unsubscribe : https://launchpad.net/~simple-scan-team More help : https://help.launchpad.net/ListHelp

