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