diff -u -r xsane-0.999-ori/src/xsane.c xsane-0.999/src/xsane.c
--- xsane-0.999-ori/src/xsane.c	2010-11-16 21:57:51.000000000 +0100
+++ xsane-0.999/src/xsane.c	2019-05-03 20:27:04.731956317 +0200
@@ -48,6 +48,89 @@
 
 #include <sys/wait.h>
 
+/*
+ * Patch to add minimal DBus support to suit my specific needs, on Linux.
+ * 
+ * Saleem Edah-Tally, M. D. <nmset@netcourrier.com>.
+   This patch is not part of the XSANE package.
+   Please note that programming is my hobby.
+
+   This patch 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 2 of the License, or
+   (at your option) any later version.
+
+   This patch is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Mainly from https://gist.github.com/dradtke/4949546
+static const gchar introspection_xml[] =
+	"<node name='/org/xsane/remote'>"
+        "  <interface name='org.xsane.remote'>"
+        "    <method name='IsAlive'>"
+        "        <arg type='b' name='alive' direction='out'/>"
+        "    </method>"
+        "    <method name='GetScanMode'>"
+        "        <arg type='i' name='curMode' direction='out'/>"
+        "    </method>"
+        "    <method name='DoScan'>"
+        "        <arg type='s' name='prefFileName' direction='out'/>"
+        "    </method>"
+        "    <method name='GetFileName'>"
+        "        <arg type='s' name='prefFileName' direction='out'/>"
+        "    </method>"
+        "    <method name='SetCounterLength'>"
+        "        <arg type='i' name='newLen' direction='in'/>"
+        "        <arg type='i' name='prevLen' direction='out'/>"
+        "    </method>"
+        "    <method name='GetCounterLength'>"
+        "        <arg type='i' name='curLen' direction='out'/>"
+        "    </method>"
+        "    <method name='SetCounterStep'>"
+        "        <arg type='i' name='newStep' direction='in'/>"
+        "        <arg type='i' name='prevStep' direction='out'/>"
+        "    </method>"
+        "    <method name='GetCounterStep'>"
+        "        <arg type='i' name='curStep' direction='out'/>"
+        "    </method>"
+        "    <method name='SetADFPagesMax'>"
+        "        <arg type='i' name='newMax' direction='in'/>"
+        "        <arg type='i' name='prevMax' direction='out'/>"
+        "    </method>"
+        "    <method name='GetADFPagesMax'>"
+        "        <arg type='i' name='curMax' direction='out'/>"
+        "    </method>"
+        "    <method name='SetFileName'>"
+        "        <arg type='s' name='newFileName' direction='in'/>"
+        "        <arg type='s' name='prevFileName' direction='out'/>"
+        "    </method>"
+        "    <method name='IsScanning'>"
+        "        <arg type='b' name='scanning' direction='out'/>"
+        "    </method>"
+        "    <method name='GetDeviceText'>"
+        "        <arg type='s' name='deviceText' direction='out'/>"
+        "    </method>"
+        "    <signal name='ScanDoneStatus'>"
+        "        <arg type='i' name='status' direction='out'/>"
+        "    </signal>"
+        "    <signal name='ScanDialogCompletion'>"
+        "        <arg type='b' name='completed' direction='out'/>"
+        "    </signal>"
+        "    <signal name='OnSaveImageAs'>"
+        "        <arg type='s' name='savedFileName' direction='out'/>"
+        "    </signal>"
+        "    <signal name='OnCancel'>"
+        "    </signal>"
+        "  </interface>"
+        "</node>";
+
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
 struct option long_options[] =
@@ -214,6 +297,137 @@
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
+/*
+ * Handle method calls
+ */
+static void handle_method_call(GDBusConnection *conn,
+                               const gchar *sender,
+                               const gchar *object_path,
+                               const gchar *interface_name,
+                               const gchar *method_name,
+                               GVariant *parameters,
+                               GDBusMethodInvocation *invocation,
+                               gpointer user_data)
+{
+    if (!g_strcmp0(method_name, "IsAlive")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", TRUE));
+        return;
+    }
+    if (!g_strcmp0(method_name, "SetCounterLength")) {
+        guint newLen;
+        guint prevLen;
+        prevLen = preferences.filename_counter_len;
+        g_variant_get(parameters, "(i)", &newLen);
+        preferences.filename_counter_len = newLen;
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", prevLen));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetCounterLength")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", preferences.filename_counter_len));
+        return;
+    }
+    if (!g_strcmp0(method_name, "SetCounterStep")) {
+        guint newStep;
+        guint prevStep;
+        prevStep = preferences.filename_counter_step;
+        g_variant_get(parameters, "(i)", &newStep);
+        preferences.filename_counter_step = newStep;
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", prevStep));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetCounterStep")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", preferences.filename_counter_step));
+        return;
+    }
+    if (!g_strcmp0(method_name, "SetADFPagesMax")) {
+        guint newMax;
+        guint prevMax;
+        prevMax = preferences.adf_pages_max;
+        g_variant_get(parameters, "(i)", &newMax);
+        preferences.adf_pages_max = newMax;
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", prevMax));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetADFPagesMax")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", preferences.adf_pages_max));
+        return;
+    }
+    if (!g_strcmp0(method_name, "SetFileName")) {
+        gchar *newFileName;
+        gchar * prevFileName = strdup(preferences.filename);
+        g_variant_get(parameters, "(s)", &newFileName);
+        if (preferences.filename)
+            free((void *) preferences.filename);
+        preferences.filename = strdup(newFileName);
+        xsane_set_filename(newFileName);
+        g_free(newFileName);
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", prevFileName));
+        g_free(prevFileName);
+        return;
+    }
+    if (!g_strcmp0(method_name, "DoScan")) {
+        xsane_scan_dialog(NULL);
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", preferences.filename));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetScanMode")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", preferences.xsane_mode));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetFileName")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", preferences.filename));
+        return;
+    }
+    if (!g_strcmp0(method_name, "GetDeviceText")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", xsane.device_text));
+        return;
+    }
+    if (!g_strcmp0(method_name, "IsScanning")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", xsane.scanning));
+        return;
+    }
+}
+
+/*
+ * Handle property queries
+ */
+static GVariant *handle_get_property(GDBusConnection *conn,
+                                     const gchar *sender,
+                                     const gchar *object_path,
+                                     const gchar *interface_name,
+                                     const gchar *property_name,
+                                     GError **error,
+                                     gpointer user_data)
+{
+	return NULL;
+}
+
+/*
+ * Handle property modifications
+ */
+static gboolean handle_set_property(GDBusConnection *conn,
+                                    const gchar *sender,
+                                    const gchar *object_path,
+                                    const gchar *interface_name,
+                                    const gchar *property_name,
+                                    GVariant *value,
+                                    GError **error,
+                                    gpointer user_data)
+{
+	return FALSE;
+}
+
+/*
+ * Function vtable for handling methods and properties
+ */
+static const GDBusInterfaceVTable interface_vtable = {
+	&handle_method_call,
+	&handle_get_property,
+	&handle_set_property
+};
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
 static void xsane_threshold_changed()
 {
   DBG(DBG_proc, "xsane_threshold_changed\n");
@@ -5973,7 +6187,45 @@
   snprintf(buf, sizeof(buf), "%s\n\n%s", ERR_NO_DEVICES, HELP_NO_DEVICES);
   xsane_back_gtk_decision(WINDOW_NO_DEVICES, (gchar**) no_device_xpm, buf, BUTTON_CLOSE, NULL, TRUE);
 }
+/* ---------------------------------------------------------------------------------------------------------------------- */
+static gpointer start_dbus_server( )
+{
+    // get the bus connection
+    GError *error = NULL;
+    connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
+    if (error != NULL) {
+            connection = NULL;
+            return( NULL );
+    }
+    const pid_t pid = getpid();
+    char spid[8];
+    sprintf(spid, "%d", pid);
+    char serviceName[1024] = {0};
+    snprintf(serviceName, sizeof(serviceName), "%s-%s", "org.xsane.remote", spid);
+    
+    // Next line from http://www.freedesktop.org/software/gstreamer-sdk/data/docs/2012.5/gio/gio-Owning-Bus-Names.html#gdbus-owning-names
+        g_bus_own_name (G_BUS_TYPE_SESSION,
+                            serviceName,
+                            G_BUS_NAME_OWNER_FLAGS_REPLACE,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL);
+
+    // register our object
+    GDBusNodeInfo *introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
+    GDBusInterfaceInfo *interface_info = g_dbus_node_info_lookup_interface(introspection_data, "org.xsane.remote");
+    g_dbus_connection_register_object(connection,
+                                        "/org/xsane/remote",
+                                        interface_info,
+                                        &interface_vtable,
+                                        NULL,
+                                        NULL,
+                                        NULL);
 
+    return( NULL );
+}
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
 void xsane_interface(int argc, char **argv)
@@ -6035,7 +6287,14 @@
   memset(&act, 0, sizeof(act));
   act.sa_handler = xsane_sigchld_handler;
   sigaction(SIGCHLD, &act, 0);
-
+  
+  GError *error;
+  GThread *thread = g_thread_try_new( "dbus-thread", start_dbus_server, NULL, &error);
+    if( ! thread )
+    {
+        g_print( "Error: %s\n", error->message );
+    }
+  
   gtk_main();
   sane_exit();
 }
diff -u -r xsane-0.999-ori/src/xsane.h xsane-0.999/src/xsane.h
--- xsane-0.999-ori/src/xsane.h	2013-05-22 23:43:46.000000000 +0200
+++ xsane-0.999/src/xsane.h	2019-04-08 12:10:08.814800793 +0200
@@ -312,6 +312,10 @@
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
+GDBusConnection *connection;
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
 enum
 {
   XSANE_PATH_LOCAL_SANE = 0,
diff -u -r xsane-0.999-ori/src/xsane-save.c xsane-0.999/src/xsane-save.c
--- xsane-0.999-ori/src/xsane-save.c	2010-11-16 22:06:00.000000000 +0100
+++ xsane-0.999/src/xsane-save.c	2019-05-17 15:41:25.249525692 +0200
@@ -365,7 +365,11 @@
         if (counter < 0)
         {
           counter = 0;
-          xsane_back_gtk_warning(WARN_COUNTER_UNDERRUN, TRUE);
+          // We don't want to block the UI when used over DBus
+          //xsane_back_gtk_warning(WARN_COUNTER_UNDERRUN, TRUE);
+          char buf[TEXTBUFSIZE];
+          
+          snprintf(buf, sizeof(buf), "%s", WARN_COUNTER_UNDERRUN);
           break; /* last available number ("..999") */
         }
 
@@ -4909,8 +4913,11 @@
     xsane_back_gtk_error(buf, TRUE);
     return -1; /* error */
   }
-
-  if (setjmp(png_ptr->jmpbuf))
+  /*
+    * From https://projects.archlinux.org/svntogit/packages.git/plain/trunk/PKGBUILD?h=packages/xsane
+    * sed -i -e 's:png_ptr->jmpbuf:png_jmpbuf(png_ptr):' src/xsane-save.c
+  */
+  if (setjmp(png_jmpbuf(png_ptr)))
   {
     snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
     xsane_back_gtk_error(buf, TRUE);
@@ -5099,8 +5106,11 @@
     xsane_back_gtk_error(buf, TRUE);
     return -1; /* error */
   }
-
-  if (setjmp(png_ptr->jmpbuf))
+  /*
+  * From https://projects.archlinux.org/svntogit/packages.git/plain/trunk/PKGBUILD?h=packages/xsane
+  * sed -i -e 's:png_ptr->jmpbuf:png_jmpbuf(png_ptr):' src/xsane-save.c
+  */
+  if (setjmp(png_jmpbuf(png_ptr)))
   {
     snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
     xsane_back_gtk_error(buf, TRUE);
diff -u -r xsane-0.999-ori/src/xsane-scan.c xsane-0.999/src/xsane-scan.c
--- xsane-0.999-ori/src/xsane-scan.c	2010-11-16 21:55:53.000000000 +0100
+++ xsane-0.999/src/xsane-scan.c	2019-05-03 20:21:04.578066364 +0200
@@ -58,6 +58,25 @@
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
+void dbus_emit_signal(const gchar *sigName, const gchar *params)
+{
+    DBG(DBG_proc, "dbus_emit_signal\n");
+    GError *error = NULL;
+    if (connection != NULL) {
+        // From http://cgit.collabora.com/git/user/nicolas/glib.git/plain/gio/tests/gdbus-peer.c
+        g_dbus_connection_emit_signal (connection,
+                                     NULL,
+                                     "/org/xsane/remote",
+                                     "org.xsane.remote",
+                                     sigName,
+                                     params,
+                                     &error);
+    }
+    g_free(error);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
 static int xsane_generate_dummy_filename(int conversion_level)
 /* conversion levels: */
 /* 0 = scan */
@@ -1208,6 +1227,7 @@
         xsane_update_histogram(TRUE /* update raw */);
         xsane_update_param(0);
         xsane.header_size = 0;
+        dbus_emit_signal("ScanDoneStatus", g_variant_new ("(i)", status));
         return;
       }
     }
@@ -1238,6 +1258,7 @@
     {
       if (xsane_reduce_to_lineart())
       {
+        dbus_emit_signal("ScanDoneStatus", g_variant_new ("(i)", status));
         return; /* aborted */
       }
     }
@@ -1266,6 +1287,7 @@
 #endif /* HAVE_ANY_GIMP */
         {
           xsane_save_image_as(xsane.output_filename, xsane.dummy_filename, xsane.xsane_output_format, xsane.enable_color_management, preferences.cms_function, preferences.cms_intent, preferences.cms_bpc, xsane.progress_bar, &xsane.cancel_save);
+          dbus_emit_signal("OnSaveImageAs", g_variant_new ("(s)", xsane.output_filename));
         }
 
         xsane_progress_clear();
@@ -1611,6 +1633,7 @@
   }
 
   xsane.status_of_last_scan = status;
+  dbus_emit_signal("ScanDoneStatus", g_variant_new ("(i)", status));
 }
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
@@ -1639,6 +1662,7 @@
   {
     xsane_read_image_data(0, -1, GDK_INPUT_READ);
   }
+  dbus_emit_signal("OnCancel", NULL);
 }
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
@@ -1919,6 +1943,7 @@
         if (xsane_back_gtk_decision(ERR_HEADER_WARNING, (gchar **) warning_xpm, buf, BUTTON_OVERWRITE, BUTTON_CANCEL, TRUE /* wait */) == FALSE)
         {
           xsane_set_sensitivity(TRUE);
+          dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
           return FALSE;
         }
       }
@@ -1940,6 +1965,7 @@
         }
         xsane_back_gtk_error(buf, TRUE);
         xsane_set_sensitivity(TRUE);
+        dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
        return FALSE;
       }
 #if 0 /* this is not necessary any more because the saving routines do the conversion */
@@ -1952,6 +1978,7 @@
         if (xsane_back_gtk_decision(ERR_HEADER_INFO, (gchar **) info_xpm, buf, BUTTON_REDUCE, BUTTON_CANCEL, TRUE /* wait */) == FALSE)
         {
           xsane_set_sensitivity(TRUE);
+          dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
          return FALSE;
         }
         xsane.reduce_16bit_to_8bit = TRUE;
@@ -1964,6 +1991,7 @@
         snprintf(buf, sizeof(buf), "No RGBA data format !!!"); /* user selected output format RGBA, scanner uses other format */
         xsane_back_gtk_error(buf, TRUE);
         xsane_set_sensitivity(TRUE);
+        dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
        return FALSE;
       }
 #endif
@@ -1974,6 +2002,7 @@
       snprintf(buf, sizeof(buf), "Special format RGBA only supported in scan mode !!!");
       xsane_back_gtk_error(buf, TRUE);
       xsane_set_sensitivity(TRUE);
+      dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
      return FALSE;
     }
 #endif
@@ -1986,6 +2015,7 @@
         snprintf(buf, sizeof(buf), "Image data of type SANE_FRAME_RGBA\ncan only be saved in rgba or png format");
         xsane_back_gtk_error(buf, TRUE);
         xsane_set_sensitivity(TRUE);
+        dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", FALSE));
        return FALSE;
       }
     }
@@ -2160,6 +2190,7 @@
   xsane.scanning = TRUE; /* set marker that scan has been initiated */
 
   xsane_start_scan();
+  dbus_emit_signal("ScanDialogCompletion", g_variant_new ("(b)", TRUE));
  return FALSE;
 }
 
