rlescak / rpms / cups

Forked from rpms/cups 2 years ago
Clone
Richard Hughes 4c3d853
From db29c24e3ff75938775aa1f4072e346aeb7f6a9c Mon Sep 17 00:00:00 2001
Richard Hughes 889eca6
From: Richard Hughes <richard@hughsie.com>
Richard Hughes 889eca6
Date: Tue, 1 Mar 2011 16:05:48 +0000
Richard Hughes 889eca6
Subject: [PATCH] Add colord support to CUPS which allows Linux printers to be
Richard Hughes 889eca6
 color managed
Richard Hughes 889eca6
Richard Hughes ab7ce80
This functionality is possible because of lots of help from Tim Waugh -- thanks!
Richard Hughes 889eca6
---
Richard Hughes 889eca6
 scheduler/Makefile   |    1 +
Richard Hughes 4c3d853
 scheduler/colord.c   |  784 ++++++++++++++++++++++++++++++++++++++++++++++++++
Richard Hughes 4c3d853
 scheduler/colord.h   |   41 +++
Richard Hughes 4c3d853
 scheduler/ipp.c      |   18 +-
Richard Hughes 889eca6
 scheduler/printers.c |   69 +++++
Richard Hughes 889eca6
 scheduler/printers.h |    4 +
Richard Hughes 4c3d853
 6 files changed, 914 insertions(+), 3 deletions(-)
Richard Hughes 889eca6
 create mode 100644 scheduler/colord.c
Richard Hughes 889eca6
 create mode 100644 scheduler/colord.h
Richard Hughes 889eca6
Richard Hughes 889eca6
diff --git a/scheduler/Makefile b/scheduler/Makefile
Richard Hughes 889eca6
index 3c7da8e..b9c47d3 100644
Richard Hughes e9e839c
--- a/scheduler/Makefile
Richard Hughes e9e839c
+++ b/scheduler/Makefile
Richard Hughes 889eca6
@@ -27,6 +27,7 @@ CUPSDOBJS =	\
Richard Hughes 889eca6
 		file.o \
Richard Hughes e9e839c
 		main.o \
Richard Hughes e9e839c
 		ipp.o \
Richard Hughes e9e839c
+		colord.o \
Richard Hughes e9e839c
 		listen.o \
Richard Hughes e9e839c
 		job.o \
Richard Hughes e9e839c
 		log.o \
Richard Hughes 889eca6
diff --git a/scheduler/colord.c b/scheduler/colord.c
Richard Hughes 889eca6
new file mode 100644
Richard Hughes 4c3d853
index 0000000..bd06e1c
Richard Hughes 889eca6
--- /dev/null
Richard Hughes 889eca6
+++ b/scheduler/colord.c
Richard Hughes 4c3d853
@@ -0,0 +1,784 @@
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * "$Id$"
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ *   colord integration for the CUPS scheduler.
Richard Hughes e9e839c
+ *
Richard Hughes 4c3d853
+ *   Copyright 2011 Red Hat, Inc.
Richard Hughes e9e839c
+ *
Richard Hughes 4c3d853
+ *   Redistribution and use in source and binary forms, with or without
Richard Hughes 4c3d853
+ *   modification, are permitted provided that the following conditions
Richard Hughes 4c3d853
+ *   are met:
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   Redistributions of source code must retain the above copyright
Richard Hughes 4c3d853
+ *   notice, this list of conditions and the following disclaimer.
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   Redistributions in binary form must reproduce the above copyright
Richard Hughes 4c3d853
+ *   notice, this list of conditions and the following disclaimer in the
Richard Hughes 4c3d853
+ *   documentation and/or other materials provided with the distribution.
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Richard Hughes 4c3d853
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Richard Hughes 4c3d853
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Richard Hughes 4c3d853
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Richard Hughes 4c3d853
+ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Richard Hughes 4c3d853
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Richard Hughes 4c3d853
+ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Richard Hughes 4c3d853
+ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Richard Hughes 4c3d853
+ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
Richard Hughes 4c3d853
+ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Richard Hughes 4c3d853
+ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
Richard Hughes 4c3d853
+ *   OF THE POSSIBILITY OF SUCH DAMAGE.
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ * Contents:
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ *   colordRegisterPrinter()    - Register profiles for a printer.
Richard Hughes e9e839c
+ *   colordUnregisterPrinter()  - Unregister profiles for a printer.
Richard Hughes e9e839c
+ *   colordStart()              - Get a connection to the system bus.
Richard Hughes e9e839c
+ *   colordStop()               - Release any connection to the system bus
Richard Hughes e9e839c
+ *                                so that added profiles and devices are
Richard Hughes e9e839c
+ *                                automatically removed.
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * Include necessary headers...
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+#include "cupsd.h"
ba9bc8e
+
ba9bc8e
+#ifdef HAVE_DBUS
ba9bc8e
+
Richard Hughes e9e839c
+#include <dbus/dbus.h>
Richard Hughes e9e839c
+#include <cups/ppd-private.h>
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes e9e839c
+ * Defines used by colord. See the reference docs for further details:
Richard Hughes e9e839c
+ * http://colord.hughsie.com/api/ref-dbus.html
ba9bc8e
+ */
Richard Hughes e9e839c
+#define COLORD_SCOPE_NORMAL   "normal"    /* System scope */
Richard Hughes e9e839c
+#define COLORD_SCOPE_TEMP     "temp"      /* Process scope */
Richard Hughes e9e839c
+#define COLORD_SCOPE_DISK     "disk"      /* Lives forever, as stored in DB */
ba9bc8e
+
Richard Hughes e9e839c
+#define COLORD_RELATION_SOFT  "soft"      /* Mapping is not default */
Richard Hughes e9e839c
+#define COLORD_RELATION_HARD  "hard"      /* Explicitly mapped profile */
ba9bc8e
+
Richard Hughes e9e839c
+#define COLORD_SPACE_RGB      "rgb"       /* RGB colorspace */
Richard Hughes e9e839c
+#define COLORD_SPACE_CMYK     "cmyk"      /* CMYK colorspace */
Richard Hughes c444f44
+#define COLORD_SPACE_GRAY     "gray"      /* Gray colorspace */
Richard Hughes 46d60c6
+#define COLORD_SPACE_UNKNOWN  "unknown"   /* Unknown colorspace */
ba9bc8e
+
Richard Hughes e9e839c
+#define COLORD_MODE_PHYSICAL  "physical"  /* Actual device */
Richard Hughes e9e839c
+#define COLORD_MODE_VIRTUAL   "virtual"   /* Virtual device with no hardware */
ba9bc8e
+
Richard Hughes e9e839c
+#define COLORD_KIND_PRINTER   "printer"   /* printing output device */
ba9bc8e
+
Richard Hughes c444f44
+/* the timeout for connecting to colord */
Richard Hughes c444f44
+#define COLORD_DBUS_TIMEOUT   5000        /* ms */
Richard Hughes c444f44
+
Richard Hughes e9e839c
+/* This is static */
Richard Hughes e9e839c
+static DBusConnection *con = NULL;
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'colordStart()' - Get a connection to the system bus.
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+colordStart(void)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+  if (con)
Richard Hughes e9e839c
+    return;
Richard Hughes e9e839c
+  con = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
ba9bc8e
+}
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes e9e839c
+ * 'colordStop()' - Release any connection to the system bus so that
Richard Hughes e9e839c
+ *                  added profiles and devices are automatically removed.
c45b42d
+ */
c45b42d
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+colordStop(void)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+  if (con == NULL)
Richard Hughes e9e839c
+    return;
Richard Hughes e9e839c
+  dbus_connection_unref(con);
Richard Hughes e9e839c
+  con = NULL;
c45b42d
+}
c45b42d
+
c45b42d
+/*
Richard Hughes e9e839c
+ * 'message_dict_add_strings()' - add two strings to a dictionary.
ba9bc8e
+ */
Richard Hughes e9e839c
+
c45b42d
+static void
Richard Hughes e9e839c
+message_dict_add_strings (DBusMessageIter *dict,
Richard Hughes e9e839c
+                          const char *key,
Richard Hughes e9e839c
+                          const char *value)
c45b42d
+{
Richard Hughes e9e839c
+        DBusMessageIter entry;
Richard Hughes e9e839c
+        dbus_message_iter_open_container(dict,
Richard Hughes e9e839c
+                                         DBUS_TYPE_DICT_ENTRY,
Richard Hughes e9e839c
+                                         NULL,
Richard Hughes e9e839c
+                                         &entry);
Richard Hughes e9e839c
+        dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
Richard Hughes e9e839c
+        dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
Richard Hughes e9e839c
+        dbus_message_iter_close_container(dict, &entry);
c45b42d
+}
c45b42d
+
c45b42d
+/*
Richard Hughes e9e839c
+ * 'colordCreateProfile()' - Create a color profile for a printer.
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ * Notes: When creating the device, we can create
c45b42d
+ */
Richard Hughes e9e839c
+
ba9bc8e
+static void
Richard Hughes e9e839c
+colordCreateProfile (cups_array_t *profiles,    /* I - Profiles array */
Richard Hughes e9e839c
+                     const char *printer_name,  /* I - Printer name */
Richard Hughes e9e839c
+                     const char *qualifier,     /* I - Profile qualifier */
Richard Hughes 46d60c6
+                     const char *colorspace,    /* I - Profile colorspace */
Richard Hughes e9e839c
+                     const char **format,       /* I - Profile qualifier format */
Richard Hughes e9e839c
+                     const char *iccfile,       /* I - ICC filename */
Richard Hughes e9e839c
+                     const char *scope)         /* I - The scope of the profile, e.g.
Richard Hughes e9e839c
+                                                       'normal', 'temp' or 'disk' */
ba9bc8e
+{
Richard Hughes e9e839c
+  DBusMessage           *message = NULL;        /* D-Bus request */
Richard Hughes e9e839c
+  DBusMessage           *reply = NULL;          /* D-Bus reply */
Richard Hughes e9e839c
+  DBusMessageIter       args;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusMessageIter       dict;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusError             error;                  /* D-Bus error */
Richard Hughes e9e839c
+  char                  *idstr;                 /* Profile ID string */
Richard Hughes e9e839c
+  size_t                idstrlen;               /* Profile ID allocated length */
Richard Hughes e9e839c
+  const char            *profile_path;          /* Device object path */
Richard Hughes e9e839c
+  char                  format_str[1024];       /* Qualifier format as a string */
ba9bc8e
+
ba9bc8e
+ /*
ba9bc8e
+  * Create the profile...
ba9bc8e
+  */
ba9bc8e
+
ba9bc8e
+  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "/org/freedesktop/ColorManager",
Richard Hughes e9e839c
+                                         "org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "CreateProfile");
ba9bc8e
+
Richard Hughes e9e839c
+  /* create a profile id */
ba9bc8e
+  idstrlen = strlen (printer_name) + 1 + strlen (qualifier) + 1;
ba9bc8e
+  idstr = malloc (idstrlen);
ba9bc8e
+  if (!idstr)
ba9bc8e
+      goto out;
ba9bc8e
+  snprintf (idstr, idstrlen, "%s-%s", printer_name, qualifier);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Using profile id of %s",
Richard Hughes e9e839c
+                  idstr);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  dbus_message_iter_init_append(message, &args);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &idstr);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* mush the qualifier format into a simple string */
Richard Hughes e9e839c
+  snprintf(format_str, sizeof(format_str), "%s.%s.%s",
Richard Hughes e9e839c
+           format[0],
Richard Hughes e9e839c
+           format[1],
Richard Hughes e9e839c
+           format[2]);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* set initial properties */
Richard Hughes e9e839c
+  dbus_message_iter_open_container(&args,
Richard Hughes e9e839c
+                                   DBUS_TYPE_ARRAY,
Richard Hughes e9e839c
+                                   "{ss}",
Richard Hughes e9e839c
+                                   &dict);
Richard Hughes e9e839c
+  message_dict_add_strings(&dict, "Qualifier", qualifier);
Richard Hughes e9e839c
+  message_dict_add_strings(&dict, "Format", format_str);
Richard Hughes 46d60c6
+  message_dict_add_strings(&dict, "Colorspace", colorspace);
Richard Hughes e9e839c
+  if (iccfile != NULL)
Richard Hughes e9e839c
+    message_dict_add_strings(&dict, "Filename", iccfile);
Richard Hughes e9e839c
+  dbus_message_iter_close_container(&args, &dict);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* send syncronous */
Richard Hughes e9e839c
+  dbus_error_init(&error);
Richard Hughes c444f44
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%s)",
Richard Hughes c444f44
+                  idstr, scope);
Richard Hughes e9e839c
+  reply = dbus_connection_send_with_reply_and_block(con,
Richard Hughes e9e839c
+                                                    message,
Richard Hughes c444f44
+                                                    COLORD_DBUS_TIMEOUT,
Richard Hughes e9e839c
+                                                    &error);
Richard Hughes e9e839c
+  if (reply == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "failed to CreateProfile: %s:%s",
Richard Hughes e9e839c
+                        error.name, error.message);
Richard Hughes e9e839c
+        dbus_error_free(&error);
Richard Hughes e9e839c
+        goto out;
Richard Hughes e9e839c
+  }
ba9bc8e
+
Richard Hughes e9e839c
+  /* get reply data */
Richard Hughes e9e839c
+  dbus_message_iter_init(reply, &args);
Richard Hughes e9e839c
+  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "incorrect reply type");
Richard Hughes e9e839c
+        goto out;
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  dbus_message_iter_get_basic(&args, &profile_path);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG,
Richard Hughes e9e839c
+                  "created profile %s",
Richard Hughes e9e839c
+                  profile_path);
Richard Hughes e9e839c
+  cupsArrayAdd(profiles, strdup(profile_path));
ba9bc8e
+
ba9bc8e
+out:
Richard Hughes e9e839c
+  if (message != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(message);
Richard Hughes e9e839c
+  if (reply != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(reply);
ba9bc8e
+  free (idstr);
ba9bc8e
+}
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes e9e839c
+ * 'colordDeviceAddProfile()' - Assign a profile to a device.
ba9bc8e
+ */
ba9bc8e
+
ba9bc8e
+static void
Richard Hughes e9e839c
+colordDeviceAddProfile (const char *device_path,       /* I - Device object path */
Richard Hughes e9e839c
+                        const char *profile_path,      /* I - Profile object path */
Richard Hughes e9e839c
+                        const char *relation)          /* I - Device relation, either 'soft' or 'hard' */
ba9bc8e
+{
Richard Hughes e9e839c
+  DBusMessage           *message = NULL;        /* D-Bus request */
Richard Hughes e9e839c
+  DBusMessage           *reply = NULL;          /* D-Bus reply */
Richard Hughes e9e839c
+  DBusMessageIter       args;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusError             error;                  /* D-Bus error */
ba9bc8e
+
ba9bc8e
+  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         device_path,
Richard Hughes e9e839c
+                                         "org.freedesktop.ColorManager.Device",
Richard Hughes e9e839c
+                                         "AddProfile");
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* send profile path as the argument */
Richard Hughes e9e839c
+  dbus_message_iter_init_append(message, &args);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &relation);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &profile_path);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG,
Richard Hughes e9e839c
+                  "Calling %s:AddProfile(%s) [%s]",
Richard Hughes e9e839c
+                  device_path, profile_path, relation);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* send syncronous */
Richard Hughes e9e839c
+  dbus_error_init(&error);
Richard Hughes e9e839c
+  reply = dbus_connection_send_with_reply_and_block(con,
Richard Hughes e9e839c
+                                                    message,
Richard Hughes c444f44
+                                                    COLORD_DBUS_TIMEOUT,
Richard Hughes e9e839c
+                                                    &error);
Richard Hughes e9e839c
+  if (reply == NULL)
ba9bc8e
+  {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "failed to AddProfile: %s:%s",
Richard Hughes e9e839c
+                        error.name, error.message);
Richard Hughes e9e839c
+        dbus_error_free(&error);
Richard Hughes e9e839c
+        goto out;
ba9bc8e
+  }
Richard Hughes e9e839c
+out:
Richard Hughes e9e839c
+  if (message != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(message);
Richard Hughes e9e839c
+  if (reply != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(reply);
Richard Hughes e9e839c
+}
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'colordCreateDevice()' - Create a device and register profiles.
Richard Hughes e9e839c
+ */
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+static void
Richard Hughes e9e839c
+colordCreateDevice (cupsd_printer_t *p,         /* I - Printer */
Richard Hughes c444f44
+                    ppd_file_t *ppd,            /* I - PPD file */
Richard Hughes e9e839c
+                    cups_array_t *profiles,     /* I - Profiles array */
Richard Hughes e9e839c
+                    const char *colorspace,     /* I - Device colorspace, e.g. 'rgb' */
Richard Hughes 4c3d853
+                    char **format,              /* I - Device qualifier format */
Richard Hughes e9e839c
+                    const char *relation,       /* I - Profile relation, either 'soft' or 'hard' */
Richard Hughes e9e839c
+                    const char *scope)          /* I - The scope of the device, e.g.
Richard Hughes e9e839c
+                                                       'normal', 'temp' or 'disk' */
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+  DBusMessage           *message = NULL;        /* D-Bus request */
Richard Hughes e9e839c
+  DBusMessage           *reply = NULL;          /* D-Bus reply */
Richard Hughes e9e839c
+  DBusMessageIter       args;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusMessageIter       dict;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusError             error;                  /* D-Bus error */
Richard Hughes e9e839c
+  const char            *device_path;           /* Device object path */
Richard Hughes e9e839c
+  const char            *profile_path;          /* Profile path */
Richard Hughes e9e839c
+  char                  *default_profile_path = NULL;
Richard Hughes e9e839c
+                                                /* Default profile path */
Richard Hughes e9e839c
+  char                  device_id[1024];        /* Device ID as understood by colord */
Richard Hughes 4c3d853
+  char                  format_str[1024];       /* Qualifier format as a string */
ba9bc8e
+
ba9bc8e
+ /*
Richard Hughes e9e839c
+  * Create the device...
ba9bc8e
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
Richard Hughes e9e839c
+  device_path = device_id;
ba9bc8e
+
Richard Hughes e9e839c
+  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "/org/freedesktop/ColorManager",
Richard Hughes e9e839c
+                                         "org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "CreateDevice");
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  dbus_message_iter_init_append(message, &args);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_path);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
Richard Hughes e9e839c
+
Richard Hughes 4c3d853
+  /* mush the qualifier format into a simple string */
Richard Hughes 4c3d853
+  snprintf(format_str, sizeof(format_str), "%s.%s.%s",
Richard Hughes 4c3d853
+           format[0],
Richard Hughes 4c3d853
+           format[1],
Richard Hughes 4c3d853
+           format[2]);
Richard Hughes 4c3d853
+
Richard Hughes e9e839c
+  /* set initial properties */
Richard Hughes e9e839c
+  dbus_message_iter_open_container(&args,
Richard Hughes e9e839c
+                                 DBUS_TYPE_ARRAY,
Richard Hughes e9e839c
+                                 "{ss}",
Richard Hughes e9e839c
+                                 &dict);
Richard Hughes e9e839c
+  message_dict_add_strings(&dict, "Colorspace", colorspace);
Richard Hughes e9e839c
+  message_dict_add_strings(&dict, "Mode", COLORD_MODE_PHYSICAL);
Richard Hughes c444f44
+  if (ppd->manufacturer != NULL)
Richard Hughes c444f44
+    message_dict_add_strings(&dict, "Vendor", ppd->manufacturer);
Richard Hughes c444f44
+  if (ppd->modelname != NULL)
Richard Hughes c444f44
+    message_dict_add_strings(&dict, "Model", ppd->modelname);
Richard Hughes e9e839c
+  if (p->sanitized_device_uri != NULL)
Richard Hughes e9e839c
+    message_dict_add_strings(&dict, "Serial", p->sanitized_device_uri);
Richard Hughes 4c3d853
+  message_dict_add_strings(&dict, "Format", format_str);
Richard Hughes e9e839c
+  message_dict_add_strings(&dict, "Kind", COLORD_KIND_PRINTER);
Richard Hughes e9e839c
+  dbus_message_iter_close_container(&args, &dict);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* send syncronous */
Richard Hughes e9e839c
+  dbus_error_init(&error);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%s)",
Richard Hughes e9e839c
+                  device_id, scope);
Richard Hughes e9e839c
+  reply = dbus_connection_send_with_reply_and_block(con,
Richard Hughes e9e839c
+                                                    message,
Richard Hughes c444f44
+                                                    COLORD_DBUS_TIMEOUT,
Richard Hughes e9e839c
+                                                    &error);
Richard Hughes e9e839c
+  if (reply == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "failed to CreateDevice: %s:%s",
Richard Hughes e9e839c
+                        error.name, error.message);
Richard Hughes e9e839c
+        dbus_error_free(&error);
Richard Hughes e9e839c
+        goto out;
Richard Hughes e9e839c
+  }
ba9bc8e
+
Richard Hughes e9e839c
+  /* get reply data */
Richard Hughes e9e839c
+  dbus_message_iter_init(reply, &args);
Richard Hughes e9e839c
+  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "incorrect reply type");
Richard Hughes e9e839c
+        goto out;
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  dbus_message_iter_get_basic(&args, &device_path);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG,
Richard Hughes e9e839c
+                  "created device %s",
Richard Hughes e9e839c
+                  device_path);
c45b42d
+
Richard Hughes e9e839c
+  /* add profiles */
Richard Hughes e9e839c
+  for (profile_path = cupsArrayFirst(profiles);
Richard Hughes e9e839c
+       profile_path;
Richard Hughes e9e839c
+       profile_path = cupsArrayNext(profiles))
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    colordDeviceAddProfile (device_path, profile_path, relation);
Richard Hughes e9e839c
+  }
c45b42d
+
ba9bc8e
+out:
ba9bc8e
+  free(default_profile_path);
Richard Hughes e9e839c
+  if (message != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(message);
Richard Hughes e9e839c
+  if (reply != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(reply);
ba9bc8e
+}
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes 4c3d853
+ * 'colordFindDeviceById()' - Finds a device
Richard Hughes 4c3d853
+ */
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+static char *
Richard Hughes 4c3d853
+colordFindDeviceById (const char *device_id)      /* I - Device ID string */
Richard Hughes 4c3d853
+{
Richard Hughes 4c3d853
+  DBusMessage           *message = NULL;        /* D-Bus request */
Richard Hughes 4c3d853
+  DBusMessage           *reply = NULL;          /* D-Bus reply */
Richard Hughes 4c3d853
+  DBusMessageIter       args;                   /* D-Bus method arguments */
Richard Hughes 4c3d853
+  DBusError             error;                  /* D-Bus error */
Richard Hughes 4c3d853
+  const char           *device_path_tmp;        /* Device object path */
Richard Hughes 4c3d853
+  char                 *device_path = NULL;     /* Device object path */
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
Richard Hughes 4c3d853
+                                         "/org/freedesktop/ColorManager",
Richard Hughes 4c3d853
+                                         "org.freedesktop.ColorManager",
Richard Hughes 4c3d853
+                                         "FindDeviceById");
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+  dbus_message_iter_init_append(message, &args);
Richard Hughes 4c3d853
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+  /* send syncronous */
Richard Hughes 4c3d853
+  dbus_error_init(&error);
Richard Hughes 4c3d853
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById(%s)", device_id);
Richard Hughes 4c3d853
+  reply = dbus_connection_send_with_reply_and_block(con,
Richard Hughes 4c3d853
+                                                    message,
Richard Hughes 4c3d853
+                                                    COLORD_DBUS_TIMEOUT,
Richard Hughes 4c3d853
+                                                    &error);
Richard Hughes 4c3d853
+  if (reply == NULL)
Richard Hughes 4c3d853
+  {
Richard Hughes 4c3d853
+        /* this can happen normally on start-up */
Richard Hughes 4c3d853
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
Richard Hughes 4c3d853
+                        "failed to DeleteDevice: %s:%s",
Richard Hughes 4c3d853
+                        error.name, error.message);
Richard Hughes 4c3d853
+        dbus_error_free(&error);
Richard Hughes 4c3d853
+        goto out;
Richard Hughes 4c3d853
+  }
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+  /* get reply data */
Richard Hughes 4c3d853
+  dbus_message_iter_init(reply, &args);
Richard Hughes 4c3d853
+  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
Richard Hughes 4c3d853
+  {
Richard Hughes 4c3d853
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes 4c3d853
+                        "incorrect reply type");
Richard Hughes 4c3d853
+        goto out;
Richard Hughes 4c3d853
+  }
Richard Hughes 4c3d853
+  dbus_message_iter_get_basic(&args, &device_path_tmp);
Richard Hughes 4c3d853
+  if (device_path_tmp != NULL)
Richard Hughes 4c3d853
+    device_path = strdup (device_path_tmp);
Richard Hughes 4c3d853
+out:
Richard Hughes 4c3d853
+  if (message != NULL)
Richard Hughes 4c3d853
+    dbus_message_unref(message);
Richard Hughes 4c3d853
+  if (reply != NULL)
Richard Hughes 4c3d853
+    dbus_message_unref(reply);
Richard Hughes 4c3d853
+  return device_path;
Richard Hughes 4c3d853
+}
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+/*
Richard Hughes e9e839c
+ * 'colordDeleteDevice()' - Delete a device
ba9bc8e
+ */
ba9bc8e
+
ba9bc8e
+static void
Richard Hughes e9e839c
+colordDeleteDevice (const char *device_id)      /* I - Device ID string */
ba9bc8e
+{
Richard Hughes e9e839c
+  DBusMessage           *message = NULL;        /* D-Bus request */
Richard Hughes e9e839c
+  DBusMessage           *reply = NULL;          /* D-Bus reply */
Richard Hughes e9e839c
+  DBusMessageIter       args;                   /* D-Bus method arguments */
Richard Hughes e9e839c
+  DBusError             error;                  /* D-Bus error */
Richard Hughes 4c3d853
+  char                 *device_path;            /* Device object path */
ba9bc8e
+
ba9bc8e
+ /*
Richard Hughes 4c3d853
+  * Find the device...
Richard Hughes 4c3d853
+  */
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+  device_path = colordFindDeviceById (device_id);
Richard Hughes 4c3d853
+  if (device_path == NULL)
Richard Hughes 4c3d853
+  {
Richard Hughes 4c3d853
+        /* this can happen normally on start-up */
Richard Hughes 4c3d853
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes 4c3d853
+                        "failed to find device: %s",
Richard Hughes 4c3d853
+                        device_id);
Richard Hughes 4c3d853
+        goto out;
Richard Hughes 4c3d853
+  }
Richard Hughes 4c3d853
+
Richard Hughes 4c3d853
+ /*
Richard Hughes 4c3d853
+  * Delete the device...
ba9bc8e
+  */
ba9bc8e
+
ba9bc8e
+  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "/org/freedesktop/ColorManager",
Richard Hughes e9e839c
+                                         "org.freedesktop.ColorManager",
Richard Hughes e9e839c
+                                         "DeleteDevice");
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  dbus_message_iter_init_append(message, &args);
Richard Hughes e9e839c
+  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* send syncronous */
Richard Hughes e9e839c
+  dbus_error_init(&error);
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling DeleteDevice(%s)", device_id);
Richard Hughes e9e839c
+  reply = dbus_connection_send_with_reply_and_block(con,
Richard Hughes e9e839c
+                                                    message,
Richard Hughes c444f44
+                                                    COLORD_DBUS_TIMEOUT,
Richard Hughes e9e839c
+                                                    &error);
Richard Hughes e9e839c
+  if (reply == NULL)
ba9bc8e
+  {
Richard Hughes c444f44
+        /* this can happen normally on start-up */
72d2aba
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
72d2aba
+                        "failed to DeleteDevice: %s:%s",
Richard Hughes e9e839c
+                        error.name, error.message);
Richard Hughes e9e839c
+        dbus_error_free(&error);
Richard Hughes e9e839c
+        goto out;
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+out:
Richard Hughes 4c3d853
+  free (device_path);
Richard Hughes e9e839c
+  if (message != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(message);
Richard Hughes e9e839c
+  if (reply != NULL)
Richard Hughes e9e839c
+    dbus_message_unref(reply);
Richard Hughes e9e839c
+}
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'colordGetQualifierFormat()' - Get the qualifier format.
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ * Notes: Returns a value of "ColorSpace.MediaType.Resolution" by default
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+char **
Richard Hughes e9e839c
+colordGetQualifierFormat(ppd_file_t *ppd)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+  char                  **format;       /* Qualifier format tuple */
Richard Hughes e9e839c
+  const char            *tmp;           /* Temporary string */
Richard Hughes e9e839c
+  ppd_attr_t            *attr;          /* Profile attributes */
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* create 3-tuple */
Richard Hughes e9e839c
+  format = calloc(3, sizeof(char*));
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  /* get 1st section */
Richard Hughes e9e839c
+  tmp = "cupsICCQualifier1";
Richard Hughes e9e839c
+  attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  if (attr != NULL)
Richard Hughes e9e839c
+    tmp = attr->value;
Richard Hughes e9e839c
+  else
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "DefaultColorSpace";
Richard Hughes e9e839c
+    attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (attr == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "DefaultColorModel";
Richard Hughes e9e839c
+    attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (attr == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "";
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (strncmp(tmp, "Default", 7) == 0)
Richard Hughes e9e839c
+    tmp += 7;
Richard Hughes e9e839c
+  format[0] = strdup(tmp);
Richard Hughes e9e839c
+
Richard Hughes ab7ce80
+  /* get 2nd section */
Richard Hughes e9e839c
+  tmp = "cupsICCQualifier2";
Richard Hughes e9e839c
+  attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  if (attr != NULL)
Richard Hughes e9e839c
+    tmp = attr->value;
Richard Hughes e9e839c
+  else
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "DefaultMediaType";
Richard Hughes e9e839c
+    attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (attr == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "";
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (strncmp(tmp, "Default", 7) == 0)
Richard Hughes e9e839c
+    tmp += 7;
Richard Hughes e9e839c
+  format[1] = strdup(tmp);
Richard Hughes e9e839c
+
Richard Hughes ab7ce80
+  /* get 3rd section */
Richard Hughes e9e839c
+  tmp = "cupsICCQualifier3";
Richard Hughes e9e839c
+  attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  if (attr != NULL)
Richard Hughes e9e839c
+    tmp = attr->value;
Richard Hughes e9e839c
+  else
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "DefaultResolution";
Richard Hughes e9e839c
+    attr = ppdFindAttr(ppd, tmp, NULL);
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (attr == NULL)
Richard Hughes e9e839c
+  {
Richard Hughes e9e839c
+    tmp = "";
Richard Hughes e9e839c
+  }
Richard Hughes e9e839c
+  if (strncmp(tmp, "Default", 7) == 0)
Richard Hughes e9e839c
+    tmp += 7;
Richard Hughes e9e839c
+  format[2] = strdup(tmp);
ba9bc8e
+
Richard Hughes e9e839c
+  return format;
ba9bc8e
+}
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes e9e839c
+ * 'colordRegisterPrinter()' - Register profiles for a printer.
ba9bc8e
+ */
ba9bc8e
+
ba9bc8e
+void
Richard Hughes e9e839c
+colordRegisterPrinter(cupsd_printer_t *p)    /* I - printer */
ba9bc8e
+{
Richard Hughes e9e839c
+  char                  ppdfile[1024],  /* PPD filename */
Richard Hughes e9e839c
+                        iccfile[1024];  /* ICC filename */
Richard Hughes e9e839c
+  ppd_file_t            *ppd;           /* PPD file */
Richard Hughes e9e839c
+  cups_array_t          *profiles;      /* Profile paths array */
Richard Hughes e9e839c
+  const char            *profile_key;   /* Profile keyword */
Richard Hughes e9e839c
+  ppd_attr_t            *attr;          /* Profile attributes */
Richard Hughes e9e839c
+  const char            *device_colorspace;   /* Device colorspace */
Richard Hughes e9e839c
+  char                  **format;       /* Qualifier format tuple */
Richard Hughes e9e839c
+  int                   i;              /* Loop counter */
ba9bc8e
+
ba9bc8e
+ /*
2b082bd
+  * Do nothing for discovered printers as they will have local color
2b082bd
+  * correction
2b082bd
+  */
2b082bd
+
2b082bd
+  if (p->type & CUPS_PRINTER_DISCOVERED)
2b082bd
+    return;
2b082bd
+
2b082bd
+ /*
Richard Hughes e9e839c
+  * Ensure we have a DBus connection
ba9bc8e
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  colordStart();
Richard Hughes ab7ce80
+  if (con == NULL)
Richard Hughes ab7ce80
+    return;
ba9bc8e
+
ba9bc8e
+ /*
ba9bc8e
+  * Try opening the PPD file for this printer...
ba9bc8e
+  */
ba9bc8e
+
ba9bc8e
+  snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
ba9bc8e
+  if ((ppd = ppdOpenFile(ppdfile)) == NULL)
Richard Hughes e9e839c
+  {
2b082bd
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
Richard Hughes e9e839c
+                    "cannot open %s",
Richard Hughes e9e839c
+                    ppdfile);
ba9bc8e
+    return;
Richard Hughes e9e839c
+  }
ba9bc8e
+
ba9bc8e
+ /*
Richard Hughes e9e839c
+  * Find out the qualifier format
ba9bc8e
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  format = colordGetQualifierFormat(ppd);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * See if we have any embedded profiles...
Richard Hughes e9e839c
+  */
Richard Hughes e9e839c
+
Richard Hughes 889eca6
+  profiles = cupsArrayNew3 (NULL, NULL, NULL, 0, NULL,
Richard Hughes 889eca6
+                            (cups_afree_func_t) free);
Richard Hughes c444f44
+  profile_key = "cupsICCProfile";
Richard Hughes e9e839c
+  attr = ppdFindAttr(ppd, profile_key, NULL);
Richard Hughes e9e839c
+  for (; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL))
ba9bc8e
+    if (attr->spec[0] && attr->value && attr->value[0])
ba9bc8e
+    {
ba9bc8e
+      if (attr->value[0] != '/')
Richard Hughes e9e839c
+        snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
Richard Hughes e9e839c
+                 attr->value);
ba9bc8e
+      else
Richard Hughes e9e839c
+        strlcpy(iccfile, attr->value, sizeof(iccfile));
ba9bc8e
+
ba9bc8e
+      if (access(iccfile, 0))
ba9bc8e
+      {
Richard Hughes e9e839c
+        cupsdLogMessage(CUPSD_LOG_WARN,
Richard Hughes e9e839c
+                        "no access to %s",
Richard Hughes e9e839c
+                        iccfile);
Richard Hughes e9e839c
+        continue;
ba9bc8e
+      }
ba9bc8e
+
Richard Hughes e9e839c
+      colordCreateProfile(profiles,
Richard Hughes e9e839c
+                          p->name,
Richard Hughes e9e839c
+                          attr->spec,
Richard Hughes 46d60c6
+                          COLORD_SPACE_UNKNOWN,
Richard Hughes e9e839c
+                          (const char **)format,
Richard Hughes e9e839c
+                          iccfile,
Richard Hughes e9e839c
+                          COLORD_SCOPE_TEMP);
ba9bc8e
+    }
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Add the grayscale profile first.  We always have a grayscale profile.
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  colordCreateProfile(profiles,
Richard Hughes e9e839c
+                      p->name,
Richard Hughes e9e839c
+                      "Gray..",
Richard Hughes 46d60c6
+                      COLORD_SPACE_GRAY,
Richard Hughes e9e839c
+                      (const char **)format,
Richard Hughes e9e839c
+                      NULL,
Richard Hughes e9e839c
+                      COLORD_SCOPE_TEMP);
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Then add the RGB/CMYK/DeviceN color profile...
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  device_colorspace = "unknown";
Richard Hughes e9e839c
+  switch (ppd->colorspace)
ba9bc8e
+  {
Richard Hughes e9e839c
+    case PPD_CS_RGB :
Richard Hughes e9e839c
+    case PPD_CS_CMY :
Richard Hughes e9e839c
+        device_colorspace = COLORD_SPACE_RGB;
Richard Hughes e9e839c
+        colordCreateProfile(profiles,
Richard Hughes e9e839c
+                            p->name,
Richard Hughes e9e839c
+                            "RGB..",
Richard Hughes 46d60c6
+                            COLORD_SPACE_RGB,
Richard Hughes e9e839c
+                            (const char **)format,
Richard Hughes e9e839c
+                            NULL,
Richard Hughes e9e839c
+                            COLORD_SCOPE_TEMP);
Richard Hughes e9e839c
+        break;
Richard Hughes e9e839c
+    case PPD_CS_RGBK :
Richard Hughes e9e839c
+    case PPD_CS_CMYK :
Richard Hughes e9e839c
+        device_colorspace = COLORD_SPACE_CMYK;
Richard Hughes e9e839c
+        colordCreateProfile(profiles,
Richard Hughes e9e839c
+                            p->name,
Richard Hughes e9e839c
+                            "CMYK..",
Richard Hughes 46d60c6
+                            COLORD_SPACE_CMYK,
Richard Hughes e9e839c
+                            (const char **)format,
Richard Hughes e9e839c
+                            NULL,
Richard Hughes e9e839c
+                            COLORD_SCOPE_TEMP);
Richard Hughes e9e839c
+        break;
Richard Hughes e9e839c
+    case PPD_CS_GRAY :
Richard Hughes c444f44
+        device_colorspace = COLORD_SPACE_GRAY;
Richard Hughes c444f44
+        break;
Richard Hughes e9e839c
+    case PPD_CS_N :
Richard Hughes e9e839c
+        colordCreateProfile(profiles,
Richard Hughes e9e839c
+                            p->name,
Richard Hughes e9e839c
+                            "DeviceN..",
Richard Hughes 46d60c6
+                            COLORD_SPACE_UNKNOWN,
Richard Hughes e9e839c
+                            (const char **)format,
Richard Hughes e9e839c
+                            NULL,
Richard Hughes e9e839c
+                            COLORD_SCOPE_TEMP);
Richard Hughes e9e839c
+        break;
Richard Hughes e9e839c
+  }
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Register the device with colord.
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
Richard Hughes e9e839c
+                  p->name);
Richard Hughes e9e839c
+  colordCreateDevice (p,
Richard Hughes c444f44
+                      ppd,
Richard Hughes e9e839c
+                      profiles,
Richard Hughes e9e839c
+                      device_colorspace,
Richard Hughes 4c3d853
+                      format,
Richard Hughes e9e839c
+                      COLORD_RELATION_SOFT,
Richard Hughes e9e839c
+                      COLORD_SCOPE_TEMP);
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Free any memory we used...
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  cupsArrayDelete(profiles);
Richard Hughes e9e839c
+  for (i=0; i<3; i++)
Richard Hughes e9e839c
+    free(format[i]);
Richard Hughes e9e839c
+  free(format);
ba9bc8e
+
Richard Hughes e9e839c
+  ppdClose(ppd);
Richard Hughes e9e839c
+}
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'colordUnregisterPrinter()' - Unregister profiles for a printer.
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+colordUnregisterPrinter(cupsd_printer_t *p)  /* I - printer */
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+  char                  device_id[1024];        /* Device ID as understood by colord */
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Ensure we have a DBus connection
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  colordStart();
Richard Hughes ab7ce80
+  if (con == NULL)
Richard Hughes ab7ce80
+    return;
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * Just delete the device itself, and leave the profiles registered
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
Richard Hughes e9e839c
+  colordDeleteDevice(device_id);
Richard Hughes e9e839c
+}
ba9bc8e
+
Richard Hughes e9e839c
+#endif /* HAVE_DBUS */
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * End of "$Id$".
Richard Hughes e9e839c
+ */
Richard Hughes 889eca6
diff --git a/scheduler/colord.h b/scheduler/colord.h
Richard Hughes 889eca6
new file mode 100644
Richard Hughes 4c3d853
index 0000000..75bdd3b
Richard Hughes e9e839c
--- /dev/null
Richard Hughes e9e839c
+++ b/scheduler/colord.h
Richard Hughes 4c3d853
@@ -0,0 +1,41 @@
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * "$Id$"
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ *   colord integration for the CUPS scheduler.
Richard Hughes e9e839c
+ *
Richard Hughes 4c3d853
+ *   Copyright 2011 Red Hat, Inc.
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   Redistribution and use in source and binary forms, with or without
Richard Hughes 4c3d853
+ *   modification, are permitted provided that the following conditions
Richard Hughes 4c3d853
+ *   are met:
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   Redistributions of source code must retain the above copyright
Richard Hughes 4c3d853
+ *   notice, this list of conditions and the following disclaimer.
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   Redistributions in binary form must reproduce the above copyright
Richard Hughes 4c3d853
+ *   notice, this list of conditions and the following disclaimer in the
Richard Hughes 4c3d853
+ *   documentation and/or other materials provided with the distribution.
Richard Hughes 4c3d853
+ *
Richard Hughes 4c3d853
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Richard Hughes 4c3d853
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Richard Hughes 4c3d853
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Richard Hughes 4c3d853
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Richard Hughes 4c3d853
+ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Richard Hughes 4c3d853
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Richard Hughes 4c3d853
+ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Richard Hughes 4c3d853
+ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Richard Hughes 4c3d853
+ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
Richard Hughes 4c3d853
+ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Richard Hughes 4c3d853
+ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
Richard Hughes 4c3d853
+ *   OF THE POSSIBILITY OF SUCH DAMAGE.
Richard Hughes e9e839c
+ *
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+void	colordRegisterPrinter(cupsd_printer_t *p);
Richard Hughes e9e839c
+void	colordUnregisterPrinter(cupsd_printer_t *p);
Richard Hughes e9e839c
+void	colordStart(void);
Richard Hughes e9e839c
+void	colordStop(void);
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * End of "$Id$".
Richard Hughes e9e839c
+ */
Richard Hughes 889eca6
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
Richard Hughes 4c3d853
index b9903d1..b5af36f 100644
Richard Hughes e9e839c
--- a/scheduler/ipp.c
Richard Hughes e9e839c
+++ b/scheduler/ipp.c
Richard Hughes 4c3d853
@@ -2921,17 +2921,23 @@ add_printer(cupsd_client_t  *con,	/* I - Client connection */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
     cupsdSetPrinterReasons(printer, "none");
Richard Hughes e9e839c
 
Richard Hughes e9e839c
-#ifdef __APPLE__
Richard Hughes e9e839c
    /*
Richard Hughes e9e839c
     * (Re)register color profiles...
Richard Hughes e9e839c
     */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
     if (!RunUser)
Richard Hughes e9e839c
     {
Richard Hughes e9e839c
+      cupsdCmsRegisterPrinter(printer);
ba9bc8e
+#ifdef __APPLE__
ba9bc8e
+     /*
Richard Hughes e9e839c
+      * FIXME: ideally the ColorSync stuff would be moved to colorsync.c
Richard Hughes e9e839c
+      * and the colorsyncRegisterProfiles() would be called from
Richard Hughes e9e839c
+      * cupsdCmsRegisterPrinter() in printers.c
ba9bc8e
+      */
Richard Hughes e9e839c
       apple_unregister_profiles(printer);
Richard Hughes e9e839c
       apple_register_profiles(printer);
Richard Hughes e9e839c
-    }
Richard Hughes e9e839c
 #endif /* __APPLE__ */
ba9bc8e
+    }
Richard Hughes e9e839c
   }
Richard Hughes e9e839c
 
Richard Hughes e9e839c
  /*
Richard Hughes 4c3d853
@@ -7028,11 +7034,17 @@ delete_printer(cupsd_client_t  *con,	/* I - Client connection */
Richard Hughes 889eca6
   snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, printer->name);
Richard Hughes e9e839c
   unlink(filename);
Richard Hughes e9e839c
 
Richard Hughes e9e839c
-#ifdef __APPLE__
Richard Hughes e9e839c
  /*
Richard Hughes e9e839c
   * Unregister color profiles...
Richard Hughes e9e839c
   */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
+  cupsdCmsUnregisterPrinter(printer);
Richard Hughes e9e839c
+#ifdef __APPLE__
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
+  * FIXME: ideally the ColorSync stuff would be moved to colorsync.c
Richard Hughes e9e839c
+  * and the colorsyncUnregisterPrinter() would be called from
Richard Hughes e9e839c
+  * cupsdCmsUnregisterPrinter() in printers.c
Richard Hughes e9e839c
+  */
Richard Hughes e9e839c
   apple_unregister_profiles(printer);
Richard Hughes e9e839c
 #endif /* __APPLE__ */
Richard Hughes e9e839c
 
Richard Hughes 889eca6
diff --git a/scheduler/printers.c b/scheduler/printers.c
Richard Hughes 4c3d853
index 6920801..e830499 100644
Richard Hughes e9e839c
--- a/scheduler/printers.c
Richard Hughes e9e839c
+++ b/scheduler/printers.c
24f4630
@@ -80,6 +80,9 @@
24f4630
 #  include <asl.h>
24f4630
 #endif /* __APPLE__ */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
+#ifdef HAVE_DBUS
Richard Hughes e9e839c
+# include "colord.h"
Richard Hughes e9e839c
+#endif /* HAVE_DBUS */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
 /*
Richard Hughes e9e839c
  * Local functions...
Richard Hughes 4c3d853
@@ -712,6 +715,53 @@ cupsdDeleteAllPrinters(void)
Richard Hughes e9e839c
   }
Richard Hughes e9e839c
 }
Richard Hughes e9e839c
 
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'cupsdCmsRegisterPrinter()' - Registers a printer and profiles with the CMS
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+cupsdCmsRegisterPrinter(cupsd_printer_t *p)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+#if defined(HAVE_DBUS)
Richard Hughes e9e839c
+  colordRegisterPrinter(p);
Richard Hughes e9e839c
+#endif /* defined(HAVE_DBUS) */
Richard Hughes e9e839c
+}
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'cupsdCmsUnregisterPrinter()' - Unregisters a printer and profiles with the CMS
Richard Hughes e9e839c
+ */
ba9bc8e
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+cupsdCmsUnregisterPrinter(cupsd_printer_t *p)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+#if defined(HAVE_DBUS)
Richard Hughes e9e839c
+  colordUnregisterPrinter(p);
Richard Hughes e9e839c
+#endif /* defined(HAVE_DBUS) */
ba9bc8e
+}
ba9bc8e
+
Richard Hughes e9e839c
+/*
Richard Hughes e9e839c
+ * 'cupsdCmsStart()' - Starts the CMS
Richard Hughes e9e839c
+ */
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+void
Richard Hughes e9e839c
+cupsdCmsStart(void)
Richard Hughes e9e839c
+{
Richard Hughes e9e839c
+#if defined(HAVE_DBUS)
Richard Hughes e9e839c
+  colordStart();
Richard Hughes e9e839c
+#endif /* defined(HAVE_DBUS) */
Richard Hughes e9e839c
+}
ba9bc8e
+
ba9bc8e
+/*
Richard Hughes e9e839c
+ * 'cupsdCmsStop()' - Stops the CMS
ba9bc8e
+ */
ba9bc8e
+
ba9bc8e
+void
Richard Hughes e9e839c
+cupsdCmsStop(void)
ba9bc8e
+{
Richard Hughes e9e839c
+#if defined(HAVE_DBUS)
Richard Hughes e9e839c
+  colordStop();
Richard Hughes e9e839c
+#endif /* defined(HAVE_DBUS) */
Richard Hughes e9e839c
+}
Richard Hughes e9e839c
 
Richard Hughes e9e839c
 /*
Richard Hughes e9e839c
  * 'cupsdDeletePrinter()' - Delete a printer from the system.
Richard Hughes 4c3d853
@@ -752,6 +802,12 @@ cupsdDeletePrinter(
Richard Hughes e9e839c
 		              "Job stopped.");
Richard Hughes e9e839c
 
Richard Hughes e9e839c
  /*
Richard Hughes e9e839c
+  * Unregister profiles...
Richard Hughes e9e839c
+  */
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+  cupsdCmsUnregisterPrinter(p);
Richard Hughes e9e839c
+
ba9bc8e
+ /*
Richard Hughes e9e839c
   * If this printer is the next for browsing, point to the next one...
Richard Hughes e9e839c
   */
Richard Hughes e9e839c
 
Richard Hughes 4c3d853
@@ -1418,6 +1474,12 @@ cupsdRenamePrinter(
Richard Hughes 889eca6
   }
Richard Hughes e9e839c
 
Richard Hughes e9e839c
  /*
Richard Hughes e9e839c
+  * Unregister profiles...
ba9bc8e
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  cupsdCmsUnregisterPrinter(p);
ba9bc8e
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
   * Rename the printer...
Richard Hughes e9e839c
   */
Richard Hughes e9e839c
 
Richard Hughes 4c3d853
@@ -2644,6 +2706,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
Richard Hughes e9e839c
 #endif /* __sgi */
Richard Hughes e9e839c
 
Richard Hughes e9e839c
  /*
Richard Hughes e9e839c
+  * Re-register profiles...
Richard Hughes e9e839c
+  */
ba9bc8e
+
Richard Hughes e9e839c
+  cupsdCmsUnregisterPrinter(p);
Richard Hughes e9e839c
+  cupsdCmsRegisterPrinter(p);
Richard Hughes e9e839c
+
Richard Hughes e9e839c
+ /*
Richard Hughes e9e839c
   * Let the browse protocols reflect the change
Richard Hughes e9e839c
   */
Richard Hughes e9e839c
 
Richard Hughes 889eca6
diff --git a/scheduler/printers.h b/scheduler/printers.h
Richard Hughes 889eca6
index 1751578..3820428 100644
Richard Hughes e9e839c
--- a/scheduler/printers.h
Richard Hughes e9e839c
+++ b/scheduler/printers.h
Richard Hughes 889eca6
@@ -170,6 +170,10 @@ extern const char	*cupsdValidateDest(const char *uri,
ba9bc8e
 			        	   cups_ptype_t *dtype,
ba9bc8e
 					   cupsd_printer_t **printer);
ba9bc8e
 extern void		cupsdWritePrintcap(void);
Richard Hughes e9e839c
+extern void		cupsdCmsRegisterPrinter(cupsd_printer_t *p);
Richard Hughes e9e839c
+extern void		cupsdCmsUnregisterPrinter(cupsd_printer_t *p);
Richard Hughes e9e839c
+extern void		cupsdCmsStart(void);
Richard Hughes e9e839c
+extern void		cupsdCmsStop(void);
ba9bc8e
 
ba9bc8e
 
ba9bc8e
 /*
Richard Hughes 889eca6
-- 
Richard Hughes 4c3d853
1.7.6.2
Richard Hughes 889eca6