From 7ab8c8e0307a0d58438619693c53d9844763f1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 12 Sep 2020 11:16:14 +0200 Subject: New upstream version 3.38.0 --- src/app-window.ui | 1 + src/app-window.vala | 178 +++++++++++++++++++++++-------- src/book.vala | 26 ++--- src/help-overlay.ui | 9 +- src/page-view.vala | 106 ++++++++++++++++--- src/scanner.vala | 80 +++++++------- src/simple-scan.vala | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 579 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/app-window.ui b/src/app-window.ui index e0e16c0..6f42a51 100644 --- a/src/app-window.ui +++ b/src/app-window.ui @@ -670,6 +670,7 @@ False False True + True diff --git a/src/app-window.vala b/src/app-window.vala index 30adac9..67f10a8 100644 --- a/src/app-window.vala +++ b/src/app-window.vala @@ -188,6 +188,7 @@ public class AppWindow : Gtk.ApplicationWindow public signal void start_scan (string? device, ScanOptions options); public signal void stop_scan (); + public signal void redetect (); public AppWindow () { @@ -224,7 +225,7 @@ public class AppWindow : Gtk.ApplicationWindow Gtk.ButtonsType.NONE, "%s", error_title); dialog.add_button (_("_Close"), 0); - dialog.format_secondary_text ("%s", error_text); + dialog.format_secondary_markup ("%s", error_text); dialog.run (); dialog.destroy (); } @@ -245,7 +246,7 @@ public class AppWindow : Gtk.ApplicationWindow private void update_scan_status () { - scan_button.set_sensitive(false); + scan_button.sensitive = false; if (!have_devices) { status_primary_label.set_text (/* Label shown when searching for scanners */ @@ -255,12 +256,13 @@ public class AppWindow : Gtk.ApplicationWindow } else if (get_selected_device () != null) { - scan_button.set_sensitive(true); + scan_button.sensitive = true; status_primary_label.set_text (/* Label shown when detected a scanner */ _("Ready to Scan")); status_secondary_label.set_text (get_selected_device_label ()); status_secondary_label.visible = false; device_combo.visible = true; + device_combo.sensitive = true; } else if (this.missing_driver != null) { @@ -449,7 +451,7 @@ public class AppWindow : Gtk.ApplicationWindow directory = settings.get_string ("save-directory"); if (directory == null || directory == "") - directory = Environment.get_user_special_dir (UserDirectory.DOCUMENTS); + directory = GLib.Filename.to_uri(Environment.get_user_special_dir (UserDirectory.DOCUMENTS)); var save_dialog = new Gtk.FileChooserNative (/* Save dialog: Dialog title */ _("Save As…"), @@ -458,12 +460,15 @@ public class AppWindow : Gtk.ApplicationWindow _("_Save"), _("_Cancel")); save_dialog.local_only = false; + + var save_format = settings.get_string ("save-format"); if (book_uri != null) save_dialog.set_uri (book_uri); else { - save_dialog.set_current_folder (directory); - /* Default filename to use when saving document */ - save_dialog.set_current_name (_("Scanned Document.pdf")); + save_dialog.set_current_folder_uri (directory); + /* Default filename to use when saving document. */ + /* To that filename the extension will be added, eg. "Scanned Document.pdf" */ + save_dialog.set_current_name (_("Scanned Document") + "." + mime_type_to_extension (save_format)); } /* Filter to only show images by default */ @@ -489,31 +494,32 @@ public class AppWindow : Gtk.ApplicationWindow file_type_store.set (iter, /* Save dialog: Label for saving in PDF format */ 0, _("PDF (multi-page document)"), - 1, ".pdf", + 1, "application/pdf", -1); file_type_store.append (out iter); file_type_store.set (iter, /* Save dialog: Label for saving in JPEG format */ 0, _("JPEG (compressed)"), - 1, ".jpg", + 1, "image/jpeg", -1); file_type_store.append (out iter); file_type_store.set (iter, /* Save dialog: Label for saving in PNG format */ 0, _("PNG (lossless)"), - 1, ".png", + 1, "image/png", -1); #if HAVE_WEBP file_type_store.append (out iter); file_type_store.set (iter, /* Save dialog: Label for sabing in WEBP format */ 0, _("WebP (compressed)"), - 1, ".webp", + 1, "image/webp", -1); #endif var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); box.visible = true; + box.spacing = 10; save_dialog.set_extra_widget (box); /* Label in save dialog beside combo box to choose file format (PDF, JPEG, PNG, WEBP) */ @@ -528,29 +534,47 @@ public class AppWindow : Gtk.ApplicationWindow file_type_combo.add_attribute (renderer, "text", 0); box.add (file_type_combo); + if (file_type_store.get_iter_first (out iter)) + { + do + { + string mime_type; + file_type_store.get (iter, 1, out mime_type, -1); + if (mime_type == save_format) + file_type_combo.set_active_iter (iter); + } while (file_type_store.iter_next (ref iter)); + } + /* Label in save dialog beside compression slider */ var quality_label = new Gtk.Label (_("Compression:")); box.add (quality_label); var quality_adjustment = new Gtk.Adjustment (75, 0, 100, 1, 10, 0); var quality_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, quality_adjustment); - quality_scale.width_request = 200; + quality_scale.width_request = 250; quality_scale.draw_value = false; - quality_scale.add_mark (0, Gtk.PositionType.BOTTOM, null); + var minimum_size_label = "%s".printf (_("Minimum size")); + quality_scale.add_mark (quality_adjustment.lower, Gtk.PositionType.BOTTOM, minimum_size_label); quality_scale.add_mark (75, Gtk.PositionType.BOTTOM, null); quality_scale.add_mark (90, Gtk.PositionType.BOTTOM, null); - quality_scale.add_mark (100, Gtk.PositionType.BOTTOM, null); + var full_detail_label = "%s".printf (_("Full detail")); + quality_scale.add_mark (quality_adjustment.upper, Gtk.PositionType.BOTTOM, full_detail_label); quality_adjustment.value = settings.get_int ("jpeg-quality"); quality_adjustment.value_changed.connect (() => { settings.set_int ("jpeg-quality", (int) quality_adjustment.value); }); box.add (quality_scale); - file_type_combo.set_active (0); + /* Quality not applicable to PNG */ + quality_scale.visible = quality_label.visible = (save_format != "image/png"); + file_type_combo.changed.connect (() => { - var extension = ""; + var mime_type = ""; Gtk.TreeIter i; if (file_type_combo.get_active_iter (out i)) - file_type_store.get (i, 1, out extension, -1); + { + file_type_store.get (i, 1, out mime_type, -1); + settings.set_string ("save-format", mime_type); + } var filename = save_dialog.get_current_name (); @@ -558,11 +582,11 @@ public class AppWindow : Gtk.ApplicationWindow var extension_index = filename.last_index_of_char ('.'); if (extension_index >= 0) filename = filename.slice (0, extension_index); - filename = filename + extension; + filename = filename + "." + mime_type_to_extension (mime_type); save_dialog.set_current_name (filename); /* Quality not applicable to PNG */ - quality_scale.visible = quality_label.visible = (extension != ".png"); + quality_scale.visible = quality_label.visible = (mime_type != "image/png"); }); while (true) @@ -574,25 +598,20 @@ public class AppWindow : Gtk.ApplicationWindow return null; } - var extension = ""; + var mime_type = ""; Gtk.TreeIter i; if (file_type_combo.get_active_iter (out i)) - file_type_store.get (i, 1, out extension, -1); + file_type_store.get (i, 1, out mime_type, -1); var uri = save_dialog.get_uri (); var extension_index = uri.last_index_of_char ('.'); if (extension_index < 0) - uri += extension; + uri += "." + mime_type_to_extension (mime_type); /* Check the file(s) don't already exist */ var files = new List (); - var format = uri_to_format (uri); -#if HAVE_WEBP - if (format == "jpeg" || format == "png" || format == "webp") -#else - if (format == "jpeg" || format == "png") -#endif + if (mime_type == "image/jpeg" || mime_type == "image/png" || mime_type == "image/webp") { for (var j = 0; j < book.n_pages; j++) files.append (make_indexed_file (uri, j, book.n_pages)); @@ -602,7 +621,8 @@ public class AppWindow : Gtk.ApplicationWindow if (check_overwrite (save_dialog.transient_for, files)) { - settings.set_string ("save-directory", save_dialog.get_current_folder ()); + var directory_uri = uri.substring (0, uri.last_index_of ("/") + 1); + settings.set_string ("save-directory", directory_uri); save_dialog.destroy (); return uri; } @@ -633,19 +653,47 @@ public class AppWindow : Gtk.ApplicationWindow return true; } - private string uri_to_format (string uri) + private string? mime_type_to_extension (string mime_type) { - var uri_lower = uri.down (); - if (uri_lower.has_suffix (".pdf")) + if (mime_type == "application/pdf") return "pdf"; - else if (uri_lower.has_suffix (".png")) + else if (mime_type == "image/jpeg") + return "jpg"; + else if (mime_type == "image/png") return "png"; -#if HAVE_WEBP - else if (uri_lower.has_suffix (".webp")) + else if (mime_type == "image/webp") return "webp"; -#endif else - return "jpeg"; + return null; + } + + private string? extension_to_mime_type (string extension) + { + var extension_lower = extension.down (); + if (extension_lower == "pdf") + return "application/pdf"; + else if (extension_lower == "jpg") + return "image/jpeg"; + else if (extension_lower == "png") + return "image/png"; + else if (extension_lower == "webp") + return "image/webp"; + else + return null; + } + + private string uri_to_mime_type (string uri) + { + var extension_index = uri.last_index_of_char ('.'); + if (extension_index < 0) + return "image/jpeg"; + var extension = uri.substring (extension_index + 1); + + var mime_type = extension_to_mime_type (extension); + if (mime_type == null) + return "image/jpeg"; + + return mime_type; } private async bool save_document_async () @@ -658,7 +706,7 @@ public class AppWindow : Gtk.ApplicationWindow debug ("Saving to '%s'", uri); - var format = uri_to_format (uri); + var mime_type = uri_to_mime_type (uri); var cancellable = new Cancellable (); var progress_bar = new CancellableProgressBar (_("Saving"), cancellable); @@ -667,7 +715,7 @@ public class AppWindow : Gtk.ApplicationWindow save_button.sensitive = false; try { - yield book.save_async (format, settings.get_int ("jpeg-quality"), file, (fraction) => + yield book.save_async (mime_type, settings.get_int ("jpeg-quality"), file, (fraction) => { progress_bar.set_fraction (fraction); }, cancellable); @@ -748,6 +796,9 @@ public class AppWindow : Gtk.ApplicationWindow if (scanning) stop_scan (); + have_devices = false; + /* Refresh list of devices to detect network scanners, and fix issues with disconnected scanners */ + redetect (); clear_document (); }); } @@ -773,6 +824,7 @@ public class AppWindow : Gtk.ApplicationWindow { status_primary_label.set_text (/* Label shown when scan started */ _("Contacting scanner…")); + device_combo.sensitive = false; start_scan (get_selected_device (), options); } @@ -1428,11 +1480,21 @@ public class AppWindow : Gtk.ApplicationWindow try { var dir = DirUtils.make_tmp ("simple-scan-XXXXXX"); - var type = document_hint == "text" ? "pdf" : "jpeg"; - var file = File.new_for_path (Path.build_filename (dir, "scan." + type)); - yield book.save_async (type, settings.get_int ("jpeg-quality"), file, null, null); + string mime_type, filename; + if (document_hint == "text") + { + mime_type = "application/pdf"; + filename = "scan.pdf"; + } + else + { + mime_type = "image/jpeg"; + filename = "scan.jpg"; + } + var file = File.new_for_path (Path.build_filename (dir, filename)); + yield book.save_async (mime_type, settings.get_int ("jpeg-quality"), file, null, null); var command_line = "xdg-email"; - if (type == "pdf") + if (mime_type == "application/pdf") command_line += " --attach %s".printf (file.get_path ()); else { @@ -1574,16 +1636,31 @@ public class AppWindow : Gtk.ApplicationWindow /* Instructions on how to install Brother scanner drivers */ instructions = _("Drivers for this are available on the Brother website."); break; + case "pixma": + /* Message to indicate a Canon Pixma scanner has been detected */ + message = _("You appear to have a Canon scanner, which is supported by the Pixma SANE backend."); + /* Instructions on how to resolve issue with SANE scanner drivers */ + instructions = _("Please check if your scanner is supported by SANE, otherwise report the issue to the SANE mailing list."); + break; case "samsung": /* Message to indicate a Samsung scanner has been detected */ message = _("You appear to have a Samsung scanner."); - /* Instructions on how to install Samsung scanner drivers */ - instructions = _("Drivers for this are available on the Samsung website."); + /* Instructions on how to install Samsung scanner drivers. + Because HP acquired Samsung's global printing business in 2017, the support is made on HP site. */ + instructions = _("Drivers for this are available on the HP website (HP acquired Samsung's printing business)."); break; case "hpaio": + case "smfp": /* Message to indicate a HP scanner has been detected */ message = _("You appear to have an HP scanner."); - packages_to_install = { "libsane-hpaio" }; + if (missing_driver == "hpaio") + packages_to_install = { "libsane-hpaio" }; + else + /* Instructions on how to install HP scanner drivers. + smfp is rebranded and slightly modified Samsung devices, + for example: HP Laser MFP 135a is rebranded Samsung Xpress SL-M2070. + It require custom drivers, not available in hpaio package */ + instructions = _("Drivers for this are available on the HP website."); break; case "epkowa": /* Message to indicate an Epson scanner has been detected */ @@ -1591,6 +1668,12 @@ public class AppWindow : Gtk.ApplicationWindow /* Instructions on how to install Epson scanner drivers */ instructions = _("Drivers for this are available on the Epson website."); break; + case "lexmark_nscan": + /* Message to indicate an Lexmark scanner has been detected */ + message = _("You appear to have an Lexmark scanner."); + /* Instructions on how to install Lexmark scanner drivers */ + instructions = _("Drivers for this are available on the Lexmark website."); + break; } var dialog = new Gtk.Dialog.with_buttons (/* Title of dialog giving instructions on how to install drivers */ _("Install drivers"), this, Gtk.DialogFlags.MODAL, _("_Close"), Gtk.ResponseType.CLOSE); @@ -1601,6 +1684,7 @@ public class AppWindow : Gtk.ApplicationWindow label.visible = true; label.xalign = 0f; label.vexpand = true; + label.use_markup = true; dialog.get_content_area ().add (label); var instructions_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); @@ -1780,7 +1864,7 @@ public class AppWindow : Gtk.ApplicationWindow app.set_accels_for_action ("app.print", { "P" }); app.set_accels_for_action ("app.help", { "F1" }); app.set_accels_for_action ("app.quit", { "Q" }); - app.set_accels_for_action ("win.show-help-overlay", { "F1" }); + app.set_accels_for_action ("win.show-help-overlay", { "question" }); var gear_menu = new Menu (); var section = new Menu (); diff --git a/src/book.vala b/src/book.vala index 6db2952..798fe98 100644 --- a/src/book.vala +++ b/src/book.vala @@ -136,10 +136,10 @@ public class Book : Object return pages.index (page); } - public async void save_async (string t, int q, File f, ProgressionCallback? p, Cancellable? c) throws Error + public async void save_async (string mime_type, int quality, File file, ProgressionCallback? progress_cb, Cancellable? cancellable = null) throws Error { var book_saver = new BookSaver (); - yield book_saver.save_async (this, t, q, f, p, c); + yield book_saver.save_async (this, mime_type, quality, file, progress_cb, cancellable); } } @@ -160,7 +160,7 @@ private class BookSaver * distributes all encode tasks to other threads then yield so * the ui can continue operating. The method then return once saving * is completed, cancelled, or failed */ - public async void save_async (Book book, string type, int quality, File file, ProgressionCallback? progression_callback, Cancellable? cancellable) throws Error + public async void save_async (Book book, string mime_type, int quality, File file, ProgressionCallback? progression_callback, Cancellable? cancellable) throws Error { var timer = new Timer (); @@ -184,20 +184,20 @@ private class BookSaver /* Configure an encoder */ ThreadPoolFunc? encode_delegate = null; - switch (type) + switch (mime_type) { - case "jpeg": + case "image/jpeg": encode_delegate = encode_jpeg; break; - case "png": + case "image/png": encode_delegate = encode_png; break; #if HAVE_WEBP - case "webp": + case "image/webp": encode_delegate = encode_webp; break; #endif - case "pdf": + case "application/pdf": encode_delegate = encode_pdf; break; } @@ -205,16 +205,16 @@ private class BookSaver /* Configure a writer */ ThreadFunc? write_delegate = null; - switch (type) + switch (mime_type) { - case "jpeg": - case "png": + case "image/jpeg": + case "image/png": #if HAVE_WEBP - case "webp": + case "image/webp": #endif write_delegate = write_multifile; break; - case "pdf": + case "application/pdf": write_delegate = write_pdf; break; } diff --git a/src/help-overlay.ui b/src/help-overlay.ui index b1a0127..105d876 100644 --- a/src/help-overlay.ui +++ b/src/help-overlay.ui @@ -136,7 +136,14 @@ 1 - <ctrl>F1 + F10 + Open menu + + + + + 1 + <ctrl>question Keyboard shortcuts diff --git a/src/page-view.vala b/src/page-view.vala index 91a2c82..90a8071 100644 --- a/src/page-view.vala +++ b/src/page-view.vala @@ -45,7 +45,9 @@ public class PageView : Object } } - private int border_width = 1; + private int ruler_width = 8; + + private int border_width = 2; /* True if image needs to be regenerated */ private bool update_image = true; @@ -508,12 +510,12 @@ public class PageView : Object private int get_preview_width () { - return width_ - border_width * 2; + return width_ - (border_width + ruler_width) * 2; } private int get_preview_height () { - return height_ - border_width * 2; + return height_ - (border_width + ruler_width) * 2; } private void update_page_view () @@ -569,10 +571,10 @@ public class PageView : Object var cy = page.crop_y; var cw = page.crop_width; var ch = page.crop_height; - var dx = page_to_screen_x (cx); - var dy = page_to_screen_y (cy); - var dw = page_to_screen_x (cw); - var dh = page_to_screen_y (ch); + var dx = page_to_screen_x (cx) + border_width + ruler_width; + var dy = page_to_screen_y (cy) + border_width + ruler_width; + var dw = page_to_screen_x (cw) + border_width + ruler_width; + var dh = page_to_screen_y (ch) + border_width + ruler_width; var ix = x - dx; var iy = y - dy; @@ -633,7 +635,7 @@ public class PageView : Object selected_crop_x = page.crop_x; selected_crop_y = page.crop_y; selected_crop_w = page.crop_width; - selected_crop_h = page.crop_height;; + selected_crop_h = page.crop_height; } } @@ -831,19 +833,79 @@ public class PageView : Object context.set_line_width (1); context.translate (x_offset, y_offset); + /* Draw image */ + context.translate (border_width + ruler_width, border_width + ruler_width); + Gdk.cairo_set_source_pixbuf (context, image, 0, 0); + context.paint (); + /* Draw page border */ context.set_source_rgb (0, 0, 0); context.set_line_width (border_width); - context.rectangle ((double)border_width / 2, - (double)border_width / 2, - width_ - border_width, - height_ - border_width); + + context.rectangle (0, + 0.0, + w, + h); context.stroke (); - /* Draw image */ - context.translate (border_width, border_width); - Gdk.cairo_set_source_pixbuf (context, image, 0, 0); - context.paint (); + /* Draw horizontal ruler */ + context.set_line_width (1); + var ruler_tick = 0; + var line = 0.0; + var big_ruler_tick = 5; + + while (ruler_tick <= page.width) + { + line = page_to_screen_x (ruler_tick) + 0.5; + if (big_ruler_tick == 5) + { + context.move_to (line, 0); + context.line_to (line, -ruler_width); + context.move_to (line, h); + context.line_to (line, h + ruler_width); + big_ruler_tick = 0; + } + else + { + context.move_to (line, -2); + context.line_to (line, -5); + context.move_to (line, h + 2); + context.line_to (line, h + 5); + } + ruler_tick = ruler_tick + page.dpi/5; + big_ruler_tick = big_ruler_tick + 1; + } + context.stroke (); + + /* Draw vertical ruler */ + ruler_tick = 0; + line = 0.0; + big_ruler_tick = 5; + while (ruler_tick <= page.height) + { + line = page_to_screen_y (ruler_tick) + 0.5; + + if (big_ruler_tick == 5) + { + context.move_to (0, line); + context.line_to (-ruler_width, line); + + context.move_to (w, line); + context.line_to (w + ruler_width, line); + big_ruler_tick = 0; + } + else + { + context.move_to (-2, line); + context.line_to (-5, line); + + context.move_to (w + 2, line); + context.line_to (w + 5, line); + } + ruler_tick = ruler_tick + page.dpi/5; + big_ruler_tick = big_ruler_tick + 1; + } + context.stroke (); /* Draw scan line */ if (page.is_scanning && page.scan_line > 0) @@ -907,9 +969,19 @@ public class PageView : Object context.fill (); /* Show new edge */ - context.rectangle (dx - 1.5, dy - 1.5, dw + 3, dh + 3); context.set_source_rgb (1.0, 1.0, 1.0); + context.move_to (-border_width, dy - 1.5); + context.line_to (border_width + w, dy - 1.5); + context.move_to (-border_width, dy + dh + 1.5); + context.line_to (border_width + w, dy + dh + 1.5); + context.stroke (); + + context.move_to (dx - 1.5, -border_width); + context.line_to (dx - 1.5, border_width + h); + context.move_to (dx + dw + 1.5, -border_width); + context.line_to (dx + dw + 1.5, border_width + h); context.stroke (); + context.rectangle (dx - 0.5, dy - 0.5, dw + 1, dh + 1); context.set_source_rgb (0.0, 0.0, 0.0); context.stroke (); diff --git a/src/scanner.vala b/src/scanner.vala index dc58f14..becb9fa 100644 --- a/src/scanner.vala +++ b/src/scanner.vala @@ -429,7 +429,7 @@ public class Scanner : Object return false; var status = Sane.control_option (handle, option_index, Sane.Action.SET_AUTO, null, null); - debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", (int) option_index, Sane.status_to_string (status)); + debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO, %s=auto) -> %s", (int) option_index, option.name, Sane.status_to_string (status)); if (status != Sane.Status.GOOD) warning ("Error setting default option %s: %s", option.name, Sane.strstatus(status)); @@ -443,7 +443,7 @@ public class Scanner : Object Sane.Bool v = (Sane.Bool) value; var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null); result = (bool) v; - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s) -> (%s, %s)", (int) option_index, value ? "SANE_TRUE" : "SANE_FALSE", Sane.status_to_string (status), result ? "SANE_TRUE" : "SANE_FALSE"); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=%s) -> (%s, %s)", (int) option_index, option.name, value ? "SANE_TRUE" : "SANE_FALSE", Sane.status_to_string (status), result ? "SANE_TRUE" : "SANE_FALSE"); } private void set_int_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, int value, out int result) @@ -480,7 +480,7 @@ public class Scanner : Object } var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null); - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %d) -> (%s, %d)", (int) option_index, value, Sane.status_to_string (status), (int) v); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=%d) -> (%s, %d)", (int) option_index, option.name, value, Sane.status_to_string (status), (int) v); result = (int) v; } @@ -520,7 +520,7 @@ public class Scanner : Object v_fixed = Sane.FIX (v); var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v_fixed, null); - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %f) -> (%s, %f)", (int) option_index, value, Sane.status_to_string (status), Sane.UNFIX (v_fixed)); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=%f) -> (%s, %f)", (int) option_index, option.name, value, Sane.status_to_string (status), Sane.UNFIX (v_fixed)); result = Sane.UNFIX (v_fixed); } @@ -550,9 +550,9 @@ public class Scanner : Object var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &option.range.max, null); if (option.type == Sane.ValueType.FIXED) - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, option.range.max=%f) -> (%s)", (int) option_index, Sane.UNFIX (option.range.max), Sane.status_to_string (status)); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=option.range.max=%f) -> (%s)", (int) option_index, option.name, Sane.UNFIX (option.range.max), Sane.status_to_string (status)); else - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, option.range.max=%d) -> (%s)", (int) option_index, (int) option.range.max, Sane.status_to_string (status)); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=option.range.max=%d) -> (%s)", (int) option_index, option.name, (int) option.range.max, Sane.status_to_string (status)); } private bool set_string_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, string value, out string result) @@ -568,7 +568,7 @@ public class Scanner : Object s[i] = '\0'; var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, s, null); result = (string) s; - debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, \"%s\") -> (%s, \"%s\")", (int) option_index, value, Sane.status_to_string (status), result); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s=\"%s\") -> (%s, \"%s\")", (int) option_index, option.name, value, Sane.status_to_string (status), result); return status == Sane.Status.GOOD; } @@ -918,7 +918,6 @@ public class Scanner : Object option = get_option_by_name (handle, Sane.NAME_SCAN_SOURCE, out index); if (option == null) { - debug ("SCAN_SOURCE not available, trying alternative \"doc-source\""); option = get_option_by_name (handle, "doc-source", out index); /* Samsung unified driver. LP: #892915 */ } if (option != null) @@ -932,7 +931,7 @@ public class Scanner : Object "FlatBed", "Normal", Sane.I18N ("Normal"), - "Document Table" /* Epson scanners, eg. ET-3760 */ + "Document Table" /* Epson scanners, eg. ET-3760 */ }; string[] adf_sources = @@ -1135,7 +1134,12 @@ public class Scanner : Object else set_option_to_max (handle, option, index); } - + if (job.page_width == 0) /* #90 Fix automatic mode for Epson scanners */ + { + option = get_option_by_name (handle, "scan-area", out index); + if (option != null) + set_string_option (handle, option, index, "Maximum", null); + } /* Set page size */ option = get_option_by_name (handle, Sane.NAME_PAGE_WIDTH, out index); if (option != null && job.page_width > 0.0) @@ -1147,40 +1151,34 @@ public class Scanner : Object option = get_option_by_name (handle, Sane.NAME_BRIGHTNESS, out index); if (option != null) { - if (job.brightness != 0) + if (option.type == Sane.ValueType.FIXED) { - if (option.type == Sane.ValueType.FIXED) - { - var brightness = scale_fixed (-100, 100, option, job.brightness); - set_fixed_option (handle, option, index, brightness, null); - } - else if (option.type == Sane.ValueType.INT) - { - var brightness = scale_int (-100, 100, option, job.brightness); - set_int_option (handle, option, index, brightness, null); - } - else - warning ("Unable to set brightness, please file a bug"); + var brightness = scale_fixed (-100, 100, option, job.brightness); + set_fixed_option (handle, option, index, brightness, null); } + else if (option.type == Sane.ValueType.INT) + { + var brightness = scale_int (-100, 100, option, job.brightness); + set_int_option (handle, option, index, brightness, null); + } + else + warning ("Unable to set brightness, please file a bug"); } option = get_option_by_name (handle, Sane.NAME_CONTRAST, out index); if (option != null) { - if (job.contrast != 0) + if (option.type == Sane.ValueType.FIXED) { - if (option.type == Sane.ValueType.FIXED) - { - var contrast = scale_fixed (-100, 100, option, job.contrast); - set_fixed_option (handle, option, index, contrast, null); - } - else if (option.type == Sane.ValueType.INT) - { - var contrast = scale_int (-100, 100, option, job.contrast); - set_int_option (handle, option, index, contrast, null); - } - else - warning ("Unable to set contrast, please file a bug"); + var contrast = scale_fixed (-100, 100, option, job.contrast); + set_fixed_option (handle, option, index, contrast, null); + } + else if (option.type == Sane.ValueType.INT) + { + var contrast = scale_int (-100, 100, option, job.contrast); + set_int_option (handle, option, index, contrast, null); } + else + warning ("Unable to set contrast, please file a bug"); } /* Test scanner options (hoping will not effect other scanners...) */ @@ -1294,6 +1292,16 @@ public class Scanner : Object /* Error displayed when no documents at the start of scanning */ _("Document feeder empty")); } + else if (status == Sane.Status.NO_MEM) + { + fail_scan (status, + /* Out of memory error message with help instruction. + Message written in Pango text markup language, + A carriage return makes a line break, tag makes a monospace font */ + _("Insufficient memory to perform scan.\n" + + "Try to decrease Resolution or Page Size in Preferences menu. " + + "For some scanners when scanning in high resolution, the scan size is restricted.")); + } else if (status == Sane.Status.DEVICE_BUSY) { /* If device is busy don't interrupt, but keep waiting for scanner */ diff --git a/src/simple-scan.vala b/src/simple-scan.vala index 771dc82..3f495e5 100644 --- a/src/simple-scan.vala +++ b/src/simple-scan.vala @@ -54,6 +54,7 @@ public class SimpleScan : Gtk.Application book = app.book; app.start_scan.connect (scan_cb); app.stop_scan.connect (cancel_cb); + app.redetect.connect (redetect_cb); scanner = Scanner.get_instance (); scanner.update_devices.connect (update_scan_devices_cb); @@ -542,6 +543,217 @@ public class SimpleScan : Gtk.Application 0x04f960a9, /* ADS-1600W */ }; + /* Taken from backend/pixma/pixma_mp150.c pixma_mp730.c pixma_mp750.c pixma_mp800.c in the pixma SANE backend repository */ + /* Canon Pixma IDs extracted using the following Python script + import sys + for f in sys.argv: + for l in open(f, "r").readlines(): + tokens=l.split () + if len (tokens) >= 3 and tokens[0].startswith("#define") and tokens[1].endswith("_PID") and tokens[2].startswith("0x") and not tokens[2].endswith("ffff"): + print ( "0x04a9" + tokens[2][2:] + ", /* " + tokens[1][:-4] + " * /") + */ + private const uint32 pixma_devices[] = { + 0x04a91709, /* MP150 */ + 0x04a9170a, /* MP170 */ + 0x04a9170b, /* MP450 */ + 0x04a9170c, /* MP500 */ + 0x04a91712, /* MP530 */ + 0x04a91714, /* MP160 */ + 0x04a91715, /* MP180 */ + 0x04a91716, /* MP460 */ + 0x04a91717, /* MP510 */ + 0x04a91718, /* MP600 */ + 0x04a91719, /* MP600R */ + 0x04a9172b, /* MP140 */ + 0x04a9171c, /* MX7600 */ + 0x04a91721, /* MP210 */ + 0x04a91722, /* MP220 */ + 0x04a91723, /* MP470 */ + 0x04a91724, /* MP520 */ + 0x04a91725, /* MP610 */ + 0x04a91727, /* MX300 */ + 0x04a91728, /* MX310 */ + 0x04a91729, /* MX700 */ + 0x04a9172c, /* MX850 */ + 0x04a9172e, /* MP630 */ + 0x04a9172f, /* MP620 */ + 0x04a91730, /* MP540 */ + 0x04a91731, /* MP480 */ + 0x04a91732, /* MP240 */ + 0x04a91733, /* MP260 */ + 0x04a91734, /* MP190 */ + 0x04a91735, /* MX860 */ + 0x04a91736, /* MX320 */ + 0x04a91737, /* MX330 */ + 0x04a9173a, /* MP250 */ + 0x04a9173b, /* MP270 */ + 0x04a9173c, /* MP490 */ + 0x04a9173d, /* MP550 */ + 0x04a9173e, /* MP560 */ + 0x04a9173f, /* MP640 */ + 0x04a91741, /* MX340 */ + 0x04a91742, /* MX350 */ + 0x04a91743, /* MX870 */ + 0x04a91746, /* MP280 */ + 0x04a91747, /* MP495 */ + 0x04a91748, /* MG5100 */ + 0x04a91749, /* MG5200 */ + 0x04a9174a, /* MG6100 */ + 0x04a9174d, /* MX360 */ + 0x04a9174e, /* MX410 */ + 0x04a9174f, /* MX420 */ + 0x04a91750, /* MX880 */ + 0x04a91751, /* MG2100 */ + 0x04a91752, /* MG3100 */ + 0x04a91753, /* MG4100 */ + 0x04a91754, /* MG5300 */ + 0x04a91755, /* MG6200 */ + 0x04a91757, /* MP493 */ + 0x04a91758, /* E500 */ + 0x04a91759, /* MX370 */ + 0x04a9175B, /* MX430 */ + 0x04a9175C, /* MX510 */ + 0x04a9175D, /* MX710 */ + 0x04a9175E, /* MX890 */ + 0x04a9175A, /* E600 */ + 0x04a91763, /* MG4200 */ + 0x04a9175F, /* MP230 */ + 0x04a91765, /* MG6300 */ + 0x04a91760, /* MG2200 */ + 0x04a91761, /* E510 */ + 0x04a91762, /* MG3200 */ + 0x04a91764, /* MG5400 */ + 0x04a91766, /* MX390 */ + 0x04a91767, /* E610 */ + 0x04a91768, /* MX450 */ + 0x04a91769, /* MX520 */ + 0x04a9176a, /* MX720 */ + 0x04a9176b, /* MX920 */ + 0x04a9176c, /* MG2400 */ + 0x04a9176d, /* MG2500 */ + 0x04a9176e, /* MG3500 */ + 0x04a9176f, /* MG6500 */ + 0x04a91770, /* MG6400 */ + 0x04a91771, /* MG5500 */ + 0x04a91772, /* MG7100 */ + 0x04a91774, /* MX470 */ + 0x04a91775, /* MX530 */ + 0x04a91776, /* MB5000 */ + 0x04a91777, /* MB5300 */ + 0x04a91778, /* MB2000 */ + 0x04a91779, /* MB2300 */ + 0x04a9177a, /* E400 */ + 0x04a9177b, /* E560 */ + 0x04a9177c, /* MG7500 */ + 0x04a9177e, /* MG6600 */ + 0x04a9177f, /* MG5600 */ + 0x04a91780, /* MG2900 */ + 0x04a91788, /* E460 */ + 0x04a91787, /* MX490 */ + 0x04a91789, /* E480 */ + 0x04a9178a, /* MG3600 */ + 0x04a9178b, /* MG7700 */ + 0x04a9178c, /* MG6900 */ + 0x04a9178d, /* MG6800 */ + 0x04a9178e, /* MG5700 */ + 0x04a91792, /* MB2700 */ + 0x04a91793, /* MB2100 */ + 0x04a91794, /* G3000 */ + 0x04a91795, /* G2000 */ + 0x04a9179f, /* TS9000 */ + 0x04a91800, /* TS8000 */ + 0x04a91801, /* TS6000 */ + 0x04a91802, /* TS5000 */ + 0x04a9180b, /* MG3000 */ + 0x04a9180c, /* E470 */ + 0x04a9181e, /* E410 */ + 0x04a9181d, /* G4000 */ + 0x04a91822, /* TS6100 */ + 0x04a91825, /* TS5100 */ + 0x04a91827, /* TS3100 */ + 0x04a91828, /* E3100 */ + 0x04a9178f, /* MB5400 */ + 0x04a91790, /* MB5100 */ + 0x04a91820, /* TS9100 */ + 0x04a91823, /* TR8500 */ + 0x04a91824, /* TR7500 */ + 0x04a9185c, /* TS9500 */ + 0x04a91912, /* LIDE400 */ + 0x04a91913, /* LIDE300 */ + 0x04a91821, /* TS8100 */ + 0x04a9183a, /* G2010 */ + 0x04a9183b, /* G3010 */ + 0x04a9183d, /* G4010 */ + 0x04a9183e, /* TS9180 */ + 0x04a9183f, /* TS8180 */ + 0x04a91840, /* TS6180 */ + 0x04a91841, /* TR8580 */ + 0x04a91842, /* TS8130 */ + 0x04a91843, /* TS6130 */ + 0x04a91844, /* TR8530 */ + 0x04a91845, /* TR7530 */ + 0x04a91846, /* XK50 */ + 0x04a91847, /* XK70 */ + 0x04a91854, /* TR4500 */ + 0x04a91855, /* E4200 */ + 0x04a91856, /* TS6200 */ + 0x04a91857, /* TS6280 */ + 0x04a91858, /* TS6230 */ + 0x04a91859, /* TS8200 */ + 0x04a9185a, /* TS8280 */ + 0x04a9185b, /* TS8230 */ + 0x04a9185d, /* TS9580 */ + 0x04a9185e, /* TR9530 */ + 0x04a91863, /* G7000 */ + 0x04a91865, /* G6000 */ + 0x04a91866, /* G6080 */ + 0x04a91869, /* GM4000 */ + 0x04a91873, /* XK80 */ + 0x04a9188b, /* TS5300 */ + 0x04a9188c, /* TS5380 */ + 0x04a9188d, /* TS6300 */ + 0x04a9188e, /* TS6380 */ + 0x04a9188f, /* TS7330 */ + 0x04a91890, /* TS8300 */ + 0x04a91891, /* TS8380 */ + 0x04a91892, /* TS8330 */ + 0x04a91893, /* XK60 */ + 0x04a91894, /* TS6330 */ + 0x04a918a2, /* TS3300 */ + 0x04a918a3, /* E3300 */ + 0x04a9261f, /* MP10 */ + 0x04a9262f, /* MP730 */ + 0x04a92630, /* MP700 */ + 0x04a92635, /* MP5 */ + 0x04a9263c, /* MP360 */ + 0x04a9263d, /* MP370 */ + 0x04a9263e, /* MP390 */ + 0x04a9263f, /* MP375R */ + 0x04a9264c, /* MP740 */ + 0x04a9264d, /* MP710 */ + 0x04a9265d, /* MF5730 */ + 0x04a9265e, /* MF5750 */ + 0x04a9265f, /* MF5770 */ + 0x04a92660, /* MF3110 */ + 0x04a926e6, /* IR1020 */ + 0x04a91706, /* MP750 */ + 0x04a91708, /* MP760 */ + 0x04a91707, /* MP780 */ + 0x04a9170d, /* MP800 */ + 0x04a9170e, /* MP800R */ + 0x04a91713, /* MP830 */ + 0x04a9171a, /* MP810 */ + 0x04a9171b, /* MP960 */ + 0x04a91726, /* MP970 */ + 0x04a91901, /* CS8800F */ + 0x04a9172d, /* MP980 */ + 0x04a91740, /* MP990 */ + 0x04a91908, /* CS9000F */ + 0x04a9174b, /* MG8100 */ + 0x04a91756, /* MG8200 */ + 0x04a9190d, /* CS9000F_MII */ + }; + /* Taken from uld/noarch/oem.conf in the Samsung SANE driver */ private const uint32 samsung_devices[] = { 0x04e83425, 0x04e8341c, 0x04e8342a, 0x04e8343d, 0x04e83456, 0x04e8345a, 0x04e83427, 0x04e8343a, 0x04e83428, 0x04e8343b, 0x04e83455, 0x04e83421, 0x04e83439, 0x04e83444, 0x04e8343f, 0x04e8344e, 0x04e83431, 0x04e8345c, 0x04e8344d, 0x04e83462, 0x04e83464, 0x04e83461, 0x04e83460, 0x04e8340e, 0x04e83435, 0x04e8340f, 0x04e83441, 0x04e8344f, 0x04e83413, 0x04e8341b, 0x04e8342e, 0x04e83426, 0x04e8342b, 0x04e83433, 0x04e83440, 0x04e83434, 0x04e8345b, 0x04e83457, 0x04e8341f, 0x04e83453, 0x04e8344b, 0x04e83409, 0x04e83412, 0x04e83419, 0x04e8342c, 0x04e8343c, 0x04e83432, 0x04e8342d, 0x04e83430, 0x04e8342f, @@ -549,6 +761,10 @@ public class SimpleScan : Gtk.Application 0x04e8347c, 0x04e8347e, 0x04e83481, 0x04e83482, 0x04e83331, 0x04e83332, 0x04e83483, 0x04e83484, 0x04e83485, 0x04e83478, 0x04e83325, 0x04e83327, 0x04e8346f, 0x04e83477, 0x04e83324, 0x04e83326, 0x04e83486, 0x04e83487, 0x04e83489 }; + /* Taken from uld/noarch/oem.conf in the HP/Samsung SANE driver + These devices are rebranded Samsung Multifunction Printers. */ + private const uint32 smfp_devices[] = { 0x03F0AA2A, 0x03F0CE2A, 0x03F0C02A, 0x03F0EB2A, 0x03F0F22A }; + /* Taken from /usr/share/hplip/data/models/models.dat in the HPAIO driver */ private const uint32 hpaio_devices[] = { 0x04f92311, /* HP Officejet d125xi All-in-One Printer */ @@ -1236,6 +1452,68 @@ public class SimpleScan : Gtk.Application /* Taken from epkowa.desc from iscan-data package for Epson driver */ private const uint32 epkowa_devices[] = { 0x04b80101, 0x04b80102, 0x04b80103, 0x04b80104, 0x04b80105, 0x04b80106, 0x04b80107, 0x04b80108, 0x04b80109, 0x04b8010a, 0x04b8010b, 0x04b8010c, 0x04b8010d, 0x04b8010e, 0x04b8010f, 0x04b80110, 0x04b80112, 0x04b80114, 0x04b80116, 0x04b80118, 0x04b80119, 0x04b8011a, 0x04b8011b, 0x04b8011c, 0x04b8011d, 0x04b8011e, 0x04b8011f, 0x04b80120, 0x04b80121, 0x04b80122, 0x04b80126, 0x04b80128, 0x04b80129, 0x04b8012a, 0x04b8012b, 0x04b8012c, 0x04b8012d, 0x04b8012e, 0x04b8012f, 0x04b80130, 0x04b80131, 0x04b80133, 0x04b80135, 0x04b80136, 0x04b80137, 0x04b80138, 0x04b8013a, 0x04b8013b, 0x04b8013c, 0x04b8013d, 0x04b80142, 0x04b80143, 0x04b80144, 0x04b80147, 0x04b8014a, 0x04b8014b, 0x04b80151, 0x04b80153, 0x04b80801, 0x04b80802, 0x04b80805, 0x04b80806, 0x04b80807, 0x04b80808, 0x04b8080a, 0x04b8080c, 0x04b8080d, 0x04b8080e, 0x04b8080f, 0x04b80810, 0x04b80811, 0x04b80813, 0x04b80814, 0x04b80815, 0x04b80817, 0x04b80818, 0x04b80819, 0x04b8081a, 0x04b8081c, 0x04b8081d, 0x04b8081f, 0x04b80820, 0x04b80821, 0x04b80827, 0x04b80828, 0x04b80829, 0x04b8082a, 0x04b8082b, 0x04b8082e, 0x04b8082f, 0x04b80830, 0x04b80831, 0x04b80833, 0x04b80834, 0x04b80835, 0x04b80836, 0x04b80837, 0x04b80838, 0x04b80839, 0x04b8083a, 0x04b8083c, 0x04b8083f, 0x04b80841, 0x04b80843, 0x04b80844, 0x04b80846, 0x04b80847, 0x04b80848, 0x04b80849, 0x04b8084a, 0x04b8084c, 0x04b8084d, 0x04b8084f, 0x04b80850, 0x04b80851, 0x04b80852, 0x04b80853, 0x04b80854, 0x04b80855, 0x04b80856, 0x04b8085c, 0x04b8085d, 0x04b8085e, 0x04b8085f, 0x04b80860, 0x04b80861, 0x04b80862, 0x04b80863, 0x04b80864, 0x04b80865, 0x04b80866, 0x04b80869, 0x04b8086a, 0x04b80870, 0x04b80871, 0x04b80872, 0x04b80873, 0x04b80878, 0x04b80879, 0x04b8087b, 0x04b8087c, 0x04b8087d, 0x04b8087e, 0x04b8087f, 0x04b80880, 0x04b80881, 0x04b80883, 0x04b80884, 0x04b80885, 0x04b8088f, 0x04b80890, 0x04b80891, 0x04b80892, 0x04b80893, 0x04b80894, 0x04b80895, 0x04b80896, 0x04b80897, 0x04b80898, 0x04b80899, 0x04b8089a, 0x04b8089b, 0x04b8089c, 0x04b8089d, 0x04b8089e, 0x04b8089f, 0x04b808a0, 0x04b808a1, 0x04b808a5, 0x04b808a6, 0x04b808a8, 0x04b808a9, 0x04b808aa, 0x04b808ab, 0x04b808ac, 0x04b808ad, 0x04b808ae, 0x04b808af, 0x04b808b0, 0x04b808b3, 0x04b808b4, 0x04b808b5, 0x04b808b6, 0x04b808b7, 0x04b808b8, 0x04b808b9, 0x04b808bd, 0x04b808be, 0x04b808bf, 0x04b808c0, 0x04b808c1, 0x04b808c3, 0x04b808c4, 0x04b808c5, 0x04b808c6, 0x04b808c7, 0x04b808c8, 0x04b808c9, 0x04b808ca, 0x04b808cd, 0x04b808d0 }; + + /* Taken from /usr/local/lexmark/unix_scan_drivers/etc/lexmark_nscan.conf */ + /* Lexmark IDs extracted using command: + * grep -r "usb .* /usr" --no-filename --only-matching | sed 's/usb //' | sed 's/ 0x//' | sed 's/ \/usr/,/' + */ + private const uint32 lexmark_nscan_devices[] = { + 0x043d0279, + 0x043d027a, + 0x043d01D6, + 0x043d01D7, + 0x043d01D8, + 0x043d01DC, + 0x043d01DE, + 0x043d01E0, + 0x043d01FA, + 0x043d01FB, + 0x043d01FC, + 0x043d01FD, + 0x043d01FE, + 0x043d01FF, + 0x043d01F4, + 0x043d0120, + 0x043d0121, + 0x043d0128, + 0x043d014F, + 0x043d0149, + 0x043d0152, + 0x043d0168, + 0x043d0169, + 0x043d016A, + 0x043d012D, + 0x043d01C4, + 0x043d01C5, + 0x043d01C6, + 0x043d01CF, + 0x043d01D0, + 0x043d01D1, + 0x043d01DB, + 0x043d01ED, + 0x043d01F1, + 0x043d01F5, + 0x043d0222, + 0x043d0223, + 0x043d0227, + 0x043d0228, + 0x043d022A, + 0x043d022B, + 0x043d022F, + 0x043d0230, + 0x043d0231, + 0x043d0234, + 0x043d0235, + 0x043d0244, + 0x043d0245, + 0x043d0246, + 0x043d0247, + 0x043d0248, + 0x043d024A, + 0x043d024E, + 0x043d024F + }; + /* Brother IDs extracted using the following Python * * import sys @@ -1273,9 +1551,12 @@ public class SimpleScan : Gtk.Application add_devices (driver_map, brscan2_devices, "brscan2"); add_devices (driver_map, brscan3_devices, "brscan3"); add_devices (driver_map, brscan4_devices, "brscan4"); + add_devices (driver_map, pixma_devices, "pixma"); add_devices (driver_map, samsung_devices, "samsung"); + add_devices (driver_map, smfp_devices, "smfp"); add_devices (driver_map, hpaio_devices, "hpaio"); add_devices (driver_map, epkowa_devices, "epkowa"); + add_devices (driver_map, lexmark_nscan_devices, "lexmark_nscan"); var devices = usb_context.get_devices (); for (var i = 0; i < devices.length; i++) { @@ -1547,6 +1828,12 @@ public class SimpleScan : Gtk.Application scanner.cancel (); } + private void redetect_cb (AppWindow ui) + { + scanner.redetect (); + } + + private static void log_cb (string? log_domain, LogLevelFlags log_level, string message) { string prefix; @@ -1695,7 +1982,7 @@ public class SimpleScan : Gtk.Application } catch (Error e) { - stderr.printf ("Error fixing PDF file: %s", e.message); + stderr.printf ("Error fixing PDF file: %s\n", e.message); return Posix.EXIT_FAILURE; } return Posix.EXIT_SUCCESS; @@ -1715,6 +2002,11 @@ public class SimpleScan : Gtk.Application DirUtils.create_with_parents (path, 0700); path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", "simple-scan.log", null); log_file = FileStream.open (path, "w"); + if (log_file == null ) + { + stderr.printf ("Error: Unable to open %s file for writing\n", path); + return Posix.EXIT_FAILURE; + } Log.set_default_handler (log_cb); debug ("Starting %s %s, PID=%i", args[0], VERSION, Posix.getpid ()); -- cgit v1.2.3