diff -up cups-1.4.6/scheduler/ipp.c.icc cups-1.4.6/scheduler/ipp.c --- cups-1.4.6/scheduler/ipp.c.icc 2011-01-12 16:12:56.306371255 +0000 +++ cups-1.4.6/scheduler/ipp.c 2011-01-12 16:13:02.525066340 +0000 @@ -32,10 +32,6 @@ * based upon the printer state... * add_queued_job_count() - Add the "queued-job-count" attribute for the * specified printer or class. - * apple_init_profile() - Initialize a color profile. - * apple_register_profiles() - Register color profiles for a printer. - * apple_unregister_profiles() - Remove color profiles for the specified - * printer. * apply_printer_defaults() - Apply printer default options to a job. * authenticate_job() - Set job authentication info. * cancel_all_jobs() - Cancel all print jobs. @@ -107,11 +103,9 @@ */ #include "cupsd.h" -#include #ifdef __APPLE__ # include -# include # ifdef HAVE_MEMBERSHIP_H # include # endif /* HAVE_MEMBERSHIP_H */ @@ -142,14 +136,6 @@ static void add_printer(cupsd_client_t * static void add_printer_state_reasons(cupsd_client_t *con, cupsd_printer_t *p); static void add_queued_job_count(cupsd_client_t *con, cupsd_printer_t *p); -#ifdef __APPLE__ -static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages, - CMDeviceProfileInfo *profile, unsigned id, - const char *name, const char *text, - const char *iccfile); -static void apple_register_profiles(cupsd_printer_t *p); -static void apple_unregister_profiles(cupsd_printer_t *p); -#endif /* __APPLE__ */ static void apply_printer_defaults(cupsd_printer_t *printer, cupsd_job_t *job); static void authenticate_job(cupsd_client_t *con, ipp_attribute_t *uri); @@ -2947,17 +2933,15 @@ add_printer(cupsd_client_t *con, /* I - cupsdSetPrinterReasons(printer, "none"); -#ifdef __APPLE__ /* * (Re)register color profiles... */ if (!RunUser) { - apple_unregister_profiles(printer); - apple_register_profiles(printer); + cupsdUnregisterColorProfiles(printer); + cupsdRegisterColorProfiles(printer); } -#endif /* __APPLE__ */ } /* @@ -3093,553 +3077,6 @@ add_queued_job_count( } -#ifdef __APPLE__ -/* - * 'apple_init_profile()' - Initialize a color profile. - */ - -static void -apple_init_profile( - ppd_file_t *ppd, /* I - PPD file */ - cups_array_t *languages, /* I - Languages in the PPD file */ - CMDeviceProfileInfo *profile, /* I - Profile record */ - unsigned id, /* I - Profile ID */ - const char *name, /* I - Profile name */ - const char *text, /* I - Profile UI text */ - const char *iccfile) /* I - ICC filename */ -{ - char url[1024]; /* URL for profile filename */ - CFMutableDictionaryRef dict; /* Dictionary for name */ - char *language; /* Current language */ - ppd_attr_t *attr; /* Profile attribute */ - CFStringRef cflang, /* Language string */ - cftext; /* Localized text */ - - - /* - * Build the profile name dictionary... - */ - - dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - cftext = CFStringCreateWithCString(kCFAllocatorDefault, text, - kCFStringEncodingUTF8); - - if (cftext) - { - CFDictionarySetValue(dict, CFSTR("en"), cftext); - CFRelease(cftext); - } - - if (languages) - { - /* - * Find localized names for the color profiles... - */ - - cupsArraySave(ppd->sorted_attrs); - - for (language = (char *)cupsArrayFirst(languages); - language; - language = (char *)cupsArrayNext(languages)) - { - if (iccfile) - { - if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name, - language)) == NULL) - attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language); - } - else - attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language); - - if (attr && attr->text[0]) - { - cflang = CFStringCreateWithCString(kCFAllocatorDefault, language, - kCFStringEncodingUTF8); - cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text, - kCFStringEncodingUTF8); - - if (cflang && cftext) - CFDictionarySetValue(dict, cflang, cftext); - - if (cflang) - CFRelease(cflang); - - if (cftext) - CFRelease(cftext); - } - } - - cupsArrayRestore(ppd->sorted_attrs); - } - - /* - * Fill in the profile data... - */ - - if (iccfile) - httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0, - iccfile); - - profile->dataVersion = cmDeviceProfileInfoVersion1; - profile->profileID = id; - profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase; - profile->profileName = dict; - - if (iccfile) - strlcpy(profile->profileLoc.u.pathLoc.path, iccfile, - sizeof(profile->profileLoc.u.pathLoc.path)); -} - - -/* - * 'apple_register_profiles()' - Register color profiles for a printer. - */ - -static void -apple_register_profiles( - cupsd_printer_t *p) /* I - Printer */ -{ - int i; /* Looping var */ - char ppdfile[1024], /* PPD filename */ - iccfile[1024], /* ICC filename */ - selector[PPD_MAX_NAME]; - /* Profile selection string */ - ppd_file_t *ppd; /* PPD file */ - ppd_attr_t *attr, /* Profile attributes */ - *profileid_attr,/* cupsProfileID attribute */ - *q1_attr, /* ColorModel (or other) qualifier */ - *q2_attr, /* MediaType (or other) qualifier */ - *q3_attr; /* Resolution (or other) qualifier */ - char q_keyword[PPD_MAX_NAME]; - /* Qualifier keyword */ - const char *q1_choice, /* ColorModel (or other) choice */ - *q2_choice, /* MediaType (or other) choice */ - *q3_choice; /* Resolution (or other) choice */ - const char *profile_key; /* Profile keyword */ - ppd_option_t *cm_option; /* Color model option */ - ppd_choice_t *cm_choice; /* Color model choice */ - int num_profiles; /* Number of profiles */ - CMError error; /* Last error */ - unsigned device_id, /* Printer device ID */ - profile_id, /* Profile ID */ - default_profile_id = 0; - /* Default profile ID */ - CFMutableDictionaryRef device_name; /* Printer device name dictionary */ - CFStringRef printer_name; /* Printer name string */ - CMDeviceScope scope = /* Scope of the registration */ - { - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost - }; - CMDeviceProfileArrayPtr profiles; /* Profiles */ - CMDeviceProfileInfo *profile; /* Current profile */ - cups_array_t *languages; /* Languages array */ - - - /* - * Make sure ColorSync is available... - */ - - if (CMRegisterColorDevice == NULL) - return; - - /* - * Try opening the PPD file for this printer... - */ - - snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name); - if ((ppd = ppdOpenFile(ppdfile)) == NULL) - return; - - /* - * See if we have any profiles... - */ - - if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL) - profile_key = "APTiogaProfile"; - else - { - attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); - profile_key = "cupsICCProfile"; - } - - for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL)) - if (attr->spec[0] && attr->value && attr->value[0]) - { - if (attr->value[0] != '/') - snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, - attr->value); - else - strlcpy(iccfile, attr->value, sizeof(iccfile)); - - if (access(iccfile, 0)) - continue; - - num_profiles ++; - } - - - /* - * If we have profiles, add them... - */ - - if (num_profiles > 0) - { - if (profile_key[0] == 'A') - { - /* - * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile - * attribute... - */ - - if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL && - attr->value) - default_profile_id = atoi(attr->value); - - q1_choice = q2_choice = q3_choice = NULL; - } - else - { - /* - * For CUPS PPDs, figure out the default profile selector values... - */ - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q1_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL) - q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); - - if (q1_attr && q1_attr->value && q1_attr->value[0]) - q1_choice = q1_attr->value; - else - q1_choice = ""; - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q2_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else - q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL); - - if (q2_attr && q2_attr->value && q2_attr->value[0]) - q2_choice = q2_attr->value; - else - q2_choice = NULL; - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q3_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else - q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL); - - if (q3_attr && q3_attr->value && q3_attr->value[0]) - q3_choice = q3_attr->value; - else - q3_choice = NULL; - } - - /* - * Build the array of profiles... - * - * Note: This calloc actually requests slightly more memory than needed. - */ - - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - languages = _ppdGetLanguages(ppd); - - for (profile = profiles->profiles, - attr = ppdFindAttr(ppd, profile_key, NULL); - attr; - attr = ppdFindNextAttr(ppd, profile_key, NULL)) - if (attr->spec[0] && attr->value && attr->value[0]) - { - /* - * Add this profile... - */ - - if (attr->value[0] != '/') - snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, - attr->value); - else - strlcpy(iccfile, attr->value, sizeof(iccfile)); - - if (access(iccfile, 0)) - continue; - - if (profile_key[0] == 'c') - { - cupsArraySave(ppd->sorted_attrs); - - if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID", - attr->spec)) != NULL && - profileid_attr->value && isdigit(profileid_attr->value[0] & 255)) - profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10); - else - profile_id = _ppdHashName(attr->spec); - - cupsArrayRestore(ppd->sorted_attrs); - } - else - profile_id = atoi(attr->spec); - - apple_init_profile(ppd, languages, profile, profile_id, attr->spec, - attr->text[0] ? attr->text : attr->spec, iccfile); - - profile ++; - - /* - * See if this is the default profile... - */ - - if (!default_profile_id) - { - if (q2_choice) - { - if (q3_choice) - { - snprintf(selector, sizeof(selector), "%s.%s.%s", - q1_choice, q2_choice, q3_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - - if (!default_profile_id) - { - snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, - q2_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - } - - if (!default_profile_id && q3_choice) - { - snprintf(selector, sizeof(selector), "%s..%s", q1_choice, - q3_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - - if (!default_profile_id) - { - snprintf(selector, sizeof(selector), "%s..", q1_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - } - } - - _ppdFreeLanguages(languages); - } - else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL) - { - /* - * Extract profiles from ColorModel option... - */ - - const char *profile_name; /* Name of generic profile */ - - - num_profiles = cm_option->num_choices; - - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - - for (profile = profiles->profiles, i = cm_option->num_choices, - cm_choice = cm_option->choices; - i > 0; - i --, cm_choice ++, profile ++) - { - if (!strcmp(cm_choice->choice, "Gray") || - !strcmp(cm_choice->choice, "Black")) - profile_name = "Gray"; - else if (!strcmp(cm_choice->choice, "RGB") || - !strcmp(cm_choice->choice, "CMY")) - profile_name = "RGB"; - else if (!strcmp(cm_choice->choice, "CMYK") || - !strcmp(cm_choice->choice, "KCMY")) - profile_name = "CMYK"; - else - profile_name = "DeviceN"; - - snprintf(selector, sizeof(selector), "%s..", profile_name); - profile_id = _ppdHashName(selector); - - apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice, - cm_choice->text, NULL); - - if (cm_choice->marked) - default_profile_id = profile_id; - } - } - else - { - /* - * Use the default colorspace... - */ - - attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); - - num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2; - - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - - apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."), - "Gray", "Gray", NULL); - - switch (ppd->colorspace) - { - case PPD_CS_RGB : - case PPD_CS_CMY : - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("RGB.."), "RGB", "RGB", NULL); - break; - case PPD_CS_RGBK : - case PPD_CS_CMYK : - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL); - break; - - case PPD_CS_GRAY : - if (attr) - break; - - case PPD_CS_N : - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("DeviceN.."), "DeviceN", "DeviceN", - NULL); - break; - } - } - - if (num_profiles > 0) - { - /* - * Make sure we have a default profile ID... - */ - - if (!default_profile_id) - default_profile_id = profiles->profiles[num_profiles - 1].profileID; - - /* - * Get the device ID hash and pathelogical name dictionary. - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"", - p->name); - - device_id = _ppdHashName(p->name); - device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - printer_name = CFStringCreateWithCString(kCFAllocatorDefault, - p->name, kCFStringEncodingUTF8); - - if (device_name && printer_name) - { - CFDictionarySetValue(device_name, CFSTR("en"), printer_name); - - /* - * Register the device with ColorSync... - */ - - error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id, - device_name, &scope); - - /* - * Register the profiles... - */ - - if (error == noErr) - error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id, - default_profile_id, profiles); - } - else - error = 1000; - - /* - * Clean up... - */ - - if (error != noErr) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to register ICC color profiles for \"%s\" - %d", - p->name, (int)error); - - for (profile = profiles->profiles; - num_profiles > 0; - profile ++, num_profiles --) - CFRelease(profile->profileName); - - free(profiles); - - if (printer_name) - CFRelease(printer_name); - - if (device_name) - CFRelease(device_name); - } - - ppdClose(ppd); -} - - -/* - * 'apple_unregister_profiles()' - Remove color profiles for the specified - * printer. - */ - -static void -apple_unregister_profiles( - cupsd_printer_t *p) /* I - Printer */ -{ - /* - * Make sure ColorSync is available... - */ - - if (CMUnregisterColorDevice != NULL) - CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name)); -} -#endif /* __APPLE__ */ - /* * 'apply_printer_defaults()' - Apply printer default options to a job. */ @@ -6532,7 +5969,7 @@ delete_printer(cupsd_client_t *con, /* * Unregister color profiles... */ - apple_unregister_profiles(printer); + cupsdUnregisterColorProfiles(printer); #endif /* __APPLE__ */ if (dtype & CUPS_PRINTER_CLASS) diff -up cups-1.4.6/scheduler/printers.c.icc cups-1.4.6/scheduler/printers.c --- cups-1.4.6/scheduler/printers.c.icc 2011-01-12 16:12:56.347369245 +0000 +++ cups-1.4.6/scheduler/printers.c 2011-01-12 16:13:02.535065850 +0000 @@ -5,6 +5,7 @@ * * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2011 by Red Hat Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -40,6 +41,14 @@ * cupsdValidateDest() - Validate a printer/class destination. * cupsdWritePrintcap() - Write a pseudo-printcap file for older * applications that need it... + * apple_init_profile() - Initialize a color profile. + * dbus_create_profile() - Initialise a color profile. + * dbus_create_device() - Initialise a color device. + * cupsdRegisterColorProfiles() + * - Register color profiles for a printer. + * cupsdUnregisterColorProfiles() + * - Remove color profiles for the specified + * printer. * add_printer_defaults() - Add name-default attributes to the printer * attributes. * add_printer_filter() - Add a MIME filter for a printer. @@ -64,10 +73,14 @@ */ #include "cupsd.h" +#include #include #ifdef HAVE_APPLICATIONSERVICES_H # include #endif /* HAVE_APPLICATIONSERVICES_H */ +#ifdef __APPLE__ +# include +#endif /* __APPLE__ */ #ifdef HAVE_SYS_MOUNT_H # include #endif /* HAVE_SYS_MOUNT_H */ @@ -81,6 +94,16 @@ # include #endif /* HAVE_SYS_VFS_H */ +#ifdef HAVE_DBUS +# include +# ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND +# define dbus_message_append_iter_init dbus_message_iter_init_append +# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v)) +# define dbus_message_iter_append_object_path(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_OBJECT_PATH, &(v)) +# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v)) +# endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */ +#endif /* HAVE_DBUS */ + /* * Local functions... @@ -103,6 +126,12 @@ static void write_irix_state(cupsd_print #endif /* __sgi */ static void write_xml_string(cups_file_t *fp, const char *s); +#ifdef __APPLE__ +static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages, + CMDeviceProfileInfo *profile, unsigned id, + const char *name, const char *text, + const char *iccfile); +#endif /* __APPLE__ */ /* * 'cupsdAddPrinter()' - Add a printer to the system. @@ -786,6 +815,14 @@ cupsdDeletePrinter( update ? "Job stopped due to printer being deleted." : "Job stopped."); +#ifdef HAVE_DBUS + /* + * Unregister the color profiles + */ + + cupsdUnregisterColorProfiles(p); +#endif /* HAVE_DBUS */ + /* * If this printer is the next for browsing, point to the next one... */ @@ -1533,6 +1570,14 @@ cupsdRenamePrinter( mimeDeleteType(MimeDatabase, p->prefiltertype); p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name); +#ifdef HAVE_DBUS + /* + * Unregister the color profiles + */ + + cupsdUnregisterColorProfiles(p); +#endif /* HAVE_DBUS */ + /* * Rename the printer... */ @@ -2722,6 +2767,14 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) write_irix_state(p); #endif /* __sgi */ +#ifdef HAVE_DBUS + /* + * (Re-)register the color profiles + */ + cupsdUnregisterColorProfiles(p); + cupsdRegisterColorProfiles(p); +#endif /* HAVE_DBUS */ + /* * Let the browse protocols reflect the change */ @@ -5576,6 +5629,1031 @@ write_xml_string(cups_file_t *fp, /* I - } +#ifdef __APPLE__ +/* + * 'apple_init_profile()' - Initialize a color profile. + */ + +static void +apple_init_profile( + ppd_file_t *ppd, /* I - PPD file */ + cups_array_t *languages, /* I - Languages in the PPD file */ + CMDeviceProfileInfo *profile, /* I - Profile record */ + unsigned id, /* I - Profile ID */ + const char *name, /* I - Profile name */ + const char *text, /* I - Profile UI text */ + const char *iccfile) /* I - ICC filename */ +{ + char url[1024]; /* URL for profile filename */ + CFMutableDictionaryRef dict; /* Dictionary for name */ + char *language; /* Current language */ + ppd_attr_t *attr; /* Profile attribute */ + CFStringRef cflang, /* Language string */ + cftext; /* Localized text */ + + + /* + * Build the profile name dictionary... + */ + + dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + cftext = CFStringCreateWithCString(kCFAllocatorDefault, text, + kCFStringEncodingUTF8); + + if (cftext) + { + CFDictionarySetValue(dict, CFSTR("en"), cftext); + CFRelease(cftext); + } + + if (languages) + { + /* + * Find localized names for the color profiles... + */ + + cupsArraySave(ppd->sorted_attrs); + + for (language = (char *)cupsArrayFirst(languages); + language; + language = (char *)cupsArrayNext(languages)) + { + if (iccfile) + { + if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name, + language)) == NULL) + attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language); + } + else + attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language); + + if (attr && attr->text[0]) + { + cflang = CFStringCreateWithCString(kCFAllocatorDefault, language, + kCFStringEncodingUTF8); + cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text, + kCFStringEncodingUTF8); + + if (cflang && cftext) + CFDictionarySetValue(dict, cflang, cftext); + + if (cflang) + CFRelease(cflang); + + if (cftext) + CFRelease(cftext); + } + } + + cupsArrayRestore(ppd->sorted_attrs); + } + + /* + * Fill in the profile data... + */ + + if (iccfile) + httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0, + iccfile); + + profile->dataVersion = cmDeviceProfileInfoVersion1; + profile->profileID = id; + profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase; + profile->profileName = dict; + + if (iccfile) + strlcpy(profile->profileLoc.u.pathLoc.path, iccfile, + sizeof(profile->profileLoc.u.pathLoc.path)); +} +#endif /* __APPLE__ */ + + +#if !defined(__APPLE__) && defined(HAVE_DBUS) +/* + * 'dbus_profile_profile_set_property()' - Set a property on a profile + */ +static void +dbus_profile_profile_set_property (DBusConnection *con, /* I - D-Bus connection */ + const char *object_path, /* I - DBus path */ + const char *property_name, /* I - Property name */ + const char *property_value) /* I - Property value */ +{ + DBusMessage *message; /* D-Bus message */ + DBusPendingCall *pending = NULL; /* D-Bus method call */ + DBusMessageIter args; /* D-Bus method arguments */ + + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + object_path, + "org.freedesktop.ColorManager.Profile", + "SetProperty"); + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_string(&args, property_name); + dbus_message_iter_append_string(&args, property_value); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling Profile %s SetProperty(%s=%s)", + object_path, property_name, property_value); + if (!dbus_connection_send_with_reply(con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_pending_call_block(pending); +out: + dbus_pending_call_unref(pending); + dbus_message_unref(message); +} + +/* + * 'dbus_profile_device_set_property()' - Set a property on a device + */ +static void +dbus_profile_device_set_property (DBusConnection *con, /* I - D-Bus connection */ + const char *object_path, /* I - DBus path */ + const char *property_name, /* I - Property name */ + const char *property_value) /* I - Property value */ +{ + DBusMessage *message; /* D-Bus message */ + DBusPendingCall *pending = NULL; /* D-Bus method call */ + DBusMessageIter args; /* D-Bus method arguments */ + + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + object_path, + "org.freedesktop.ColorManager.Device", + "SetProperty"); + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_string(&args, property_name); + dbus_message_iter_append_string(&args, property_value); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling Device %s SetProperty(%s=%s)", + object_path, property_name, property_value); + if (!dbus_connection_send_with_reply(con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_pending_call_block(pending); +out: + dbus_pending_call_unref(pending); + dbus_message_unref(message); +} + +/* + * 'dbus_create_profile()' - Create a color profile for a printer. + */ +static void +dbus_create_profile (cups_array_t *profiles, /* I - Profiles array */ + DBusConnection *con, /* I - D-Bus connection */ + const char *printer_name, /* I - Printer name */ + const char *qualifier, /* I - Profile qualifier */ + const char *iccfile) /* I - ICC filename */ +{ + DBusMessage *message; /* D-Bus message */ + DBusMessageIter args; /* D-Bus method arguments */ + DBusPendingCall *pending; /* D-Bus method call */ + char *path = NULL; /* Profile path */ + char *idstr; /* Profile ID string */ + size_t idstrlen; /* Profile ID allocated length */ + int options = 1; /* Options for CreateProfile */ + + /* + * Create the profile... + */ + + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + "/org/freedesktop/ColorManager", + "org.freedesktop.ColorManager", + "CreateProfile"); + + dbus_message_append_iter_init(message, &args); + idstrlen = strlen (printer_name) + 1 + strlen (qualifier) + 1; + idstr = malloc (idstrlen); + if (!idstr) + goto out; + + snprintf (idstr, idstrlen, "%s-%s", printer_name, qualifier); + dbus_message_iter_append_string(&args, idstr); + dbus_message_iter_append_uint32(&args, options); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%d)", + idstr, options); + if (!dbus_connection_send_with_reply(con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); + message = dbus_pending_call_steal_reply(pending); +// dbus_pending_call_unref(pending); <-fixme + + if (!message || + !dbus_message_iter_init(message, &args) || + dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) + goto out; + + dbus_message_iter_get_basic(&args, &path); + path = strdup(path); + cupsArrayAdd(profiles, strdup(path)); + dbus_message_unref(message); + + /* + * Set the qualifier... + */ + dbus_profile_profile_set_property (con, path, "Qualifier", qualifier); + + /* + * If we know the ICC file for it, set that now... + */ + if (iccfile) + dbus_profile_profile_set_property (con, path, "Filename", iccfile); +out: + free (path); + free (idstr); +} + + +/* + * 'dbus_create_device()' - Create a device and register profiles. + */ + +static void +dbus_create_device (DBusConnection *con, /* I - D-Bus connection */ + cupsd_printer_t *p, /* I - Printer */ + cups_array_t *profiles, /* I - Profiles array */ + const char *default_profile_id) /* I - Default profile */ +{ + DBusMessage *message; /* D-Bus message */ + DBusMessageIter args; /* D-Bus method arguments */ + DBusPendingCall *pending; /* D-Bus method call */ + const char *device_path_tmp; /* Device path data */ + char *device_path = NULL; /* Device path */ + const char *profile_path; /* Profile path */ + char *default_profile_path = NULL; + /* Default profile path */ + size_t default_path_len; + /* Length of profile path */ + int options = 1; /* Options for CreateDevice */ + + /* + * Create the device... + */ + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + "/org/freedesktop/ColorManager", + "org.freedesktop.ColorManager", + "CreateDevice"); + + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_string(&args, p->name); + dbus_message_iter_append_uint32(&args, options); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%d)", + p->name, options); + if (!dbus_connection_send_with_reply (con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); + message = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + if (!message || + !dbus_message_iter_init(message, &args) || + dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) + goto out; + + /* get device path, and duplicate so we can free the method */ + dbus_message_iter_get_basic(&args, &device_path_tmp); + device_path = strdup (device_path_tmp); + dbus_message_unref(message); + for (profile_path = cupsArrayFirst(profiles); + profile_path; + profile_path = cupsArrayNext(profiles)) + { + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + device_path, + "org.freedesktop.ColorManager.Device", + "AddProfile"); + + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_object_path(&args, profile_path); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling AddProfile(%s)", profile_path); + pending = NULL; + if (!dbus_connection_send_with_reply (con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); +// message = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + } + + /* + * Set the default profile + */ + default_path_len = strlen (p->name) + 1 + strlen (default_profile_id) + 1; + default_profile_path = malloc (default_path_len); + if (!default_profile_path) + goto out; + + snprintf(default_profile_path, default_path_len, "%s-%s", p->name, + default_profile_id); + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + device_path, + "org.freedesktop.ColorManager.Device", + "MakeProfileDefault"); + + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_string(&args, default_profile_path); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling MakeProfileDefault(%s)", + default_profile_path); + if (!dbus_connection_send_with_reply (con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); +// message = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + + /* + * Set other useful device attributes + */ + dbus_profile_device_set_property (con, device_path, "Kind", "printer"); + dbus_profile_device_set_property (con, device_path, "Model", p->make_model); + +out: + free(default_profile_path); + free(device_path); +// dbus_message_unref(message); +} + + +/* + * 'dbus_delete_device_and_profiles()' - Delete previously registered + * color device and profiles + */ + +static void +dbus_delete_device_and_profiles(cupsd_printer_t *p) /* I - Printer */ +{ + DBusConnection *con; /* System D-Bus connection */ + DBusMessage *message; /* D-Bus message */ + DBusMessageIter args, array_args; /* D-Bus method arguments */ + DBusPendingCall *pending; /* D-Bus method call */ + const char *device_path; /* Device path */ + const char *options = ""; /* Options for GetProfilesForDevice */ + cups_array_t *profile_paths; /* Profile paths array */ + char *profile_path; /* Profile path */ + + con = dbus_bus_get (DBUS_BUS_SYSTEM, NULL); + if (!con) + return; + + /* + * Get the device path + */ + + profile_paths = cupsArrayNew(NULL, NULL); + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + "/org/freedesktop/ColorManager", + "org.freedesktop.ColorManager", + "FindDeviceById"); + + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_string(&args, p->name); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById"); + if (!dbus_connection_send_with_reply(con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); + message = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + if (!message || + !dbus_message_iter_init(message, &args) || + dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) + goto out; + + dbus_message_iter_get_basic(&args, &device_path); + device_path = strdup(device_path); + + /* + * Get the profiles + */ + + dbus_message_unref(message); + message = dbus_message_new_method_call("org.freedesktop.ColorManager", + "/org/freedesktop/ColorManager", + "org.freedesktop.ColorManager", + "GetProfilesForDevice"); + + dbus_message_append_iter_init(message, &args); + dbus_message_iter_append_object_path(&args, device_path); + dbus_message_iter_append_string(&args, options); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling GetProfilesForDevice(%s,\"\")", + device_path); + if (!dbus_connection_send_with_reply(con, message, &pending, -1)) + goto out; + + dbus_connection_flush(con); + dbus_message_unref(message); + dbus_pending_call_block(pending); + message = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + if (!message || + !dbus_message_iter_init(message, &args) || + dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) + goto out; + + dbus_message_iter_recurse(&args, &array_args); + do + { + if (dbus_message_iter_get_arg_type(&array_args) == DBUS_TYPE_OBJECT_PATH) + { + dbus_message_iter_get_basic(&array_args, &profile_path); + cupsArrayAdd(profile_paths, strdup (profile_path)); + } + } while (dbus_message_iter_next(&array_args)); + + /* + * Delete each profile. + */ + + +out: + for (profile_path = cupsArrayFirst(profile_paths); + profile_path; + profile_path = cupsArrayNext(profile_paths)) + free (profile_path); + + cupsArrayDelete(profile_paths); + dbus_message_unref(message); + dbus_connection_unref(con); +} +#endif /* !defined(__APPLE__) && defined(HAVE_DBUS) */ + + +/* + * 'cupsdRegisterColorProfiles()' - Register color profiles for a printer. + */ + +void +cupsdRegisterColorProfiles( + cupsd_printer_t *p) /* I - Printer */ +{ + int i; /* Looping var */ + char ppdfile[1024], /* PPD filename */ + iccfile[1024], /* ICC filename */ + selector[PPD_MAX_NAME]; + /* Profile selection string */ + ppd_file_t *ppd; /* PPD file */ + ppd_attr_t *attr, /* Profile attributes */ + *q1_attr, /* ColorModel (or other) qualifier */ + *q2_attr, /* MediaType (or other) qualifier */ + *q3_attr; /* Resolution (or other) qualifier */ + char q_keyword[PPD_MAX_NAME]; + /* Qualifier keyword */ + const char *q1_choice, /* ColorModel (or other) choice */ + *q2_choice, /* MediaType (or other) choice */ + *q3_choice; /* Resolution (or other) choice */ + const char *profile_key; /* Profile keyword */ + ppd_option_t *cm_option; /* Color model option */ + ppd_choice_t *cm_choice; /* Color model choice */ + int num_profiles; /* Number of profiles */ +#ifdef __APPLE__ + ppd_attr_t *profileid_attr;/* cupsProfileID attribute */ + unsigned profile_id, /* Profile ID */ + default_profile_id = 0; + /* Default profile ID */ + CMError error; /* Last error */ + CFMutableDictionaryRef device_name; /* Printer device name dictionary */ + unsigned device_id; /* Printer device ID */ + CFStringRef printer_name; /* Printer name string */ + CMDeviceScope scope = /* Scope of the registration */ + { + kCFPreferencesAnyUser, + kCFPreferencesCurrentHost + }; + CMDeviceProfileArrayPtr profiles; /* Profiles */ + CMDeviceProfileInfo *profile; /* Current profile */ + cups_array_t *languages; /* Languages array */ +#elif HAVE_DBUS + const char *profile_id = NULL, + /* Profile ID */ + *default_profile_id = NULL; + /* Default profile ID */ + DBusError error; /* Error, if any */ + static DBusConnection *con; /* System D-Bus connection */ + cups_array_t *profiles; /* Profile paths array */ + char *profile_path; /* Profile path */ +#endif /* HAVE_DBUS */ + + +#ifdef __APPLE__ + /* + * Make sure ColorSync is available... + */ + + if (CMRegisterColorDevice == NULL) + return; +#elif defined(HAVE_DBUS) + if (con && !dbus_connection_get_is_connected(con)) + { + dbus_connection_unref(con); + con = NULL; + } + + if (!con) + { + dbus_error_init(&error); + + con = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (!con) + { + if (dbus_error_is_set(&error)) + cupsdLogMessage(CUPSD_LOG_DEBUG, + "D-Bus connection error: %s", error.message); + + dbus_error_free(&error); + return; + } + } + + profiles = cupsArrayNew (NULL, NULL); +#else /* defined(__APPLE__) || defined(HAVE_DBUS) */ + return; +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + /* + * Try opening the PPD file for this printer... + */ + + snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name); + if ((ppd = ppdOpenFile(ppdfile)) == NULL) + return; + + /* + * See if we have any profiles... + */ + + if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL) + profile_key = "APTiogaProfile"; + else + { + attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); + profile_key = "cupsICCProfile"; + } + + for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL)) + if (attr->spec[0] && attr->value && attr->value[0]) + { + if (attr->value[0] != '/') + snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, + attr->value); + else + strlcpy(iccfile, attr->value, sizeof(iccfile)); + + if (access(iccfile, 0)) + continue; + + num_profiles ++; + } + + + /* + * If we have profiles, add them... + */ + + if (num_profiles > 0) + { + if (profile_key[0] == 'A') + { + /* + * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile + * attribute... + */ + + if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL && + attr->value) + { +#ifdef __APPLE__ + default_profile_id = atoi(attr->value); +#elif HAVE_DBUS + default_profile_id = attr->value; +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + } + + q1_choice = q2_choice = q3_choice = NULL; + } + else + { + /* + * For CUPS PPDs, figure out the default profile selector values... + */ + + if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL && + attr->value && attr->value[0]) + { + snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); + q1_attr = ppdFindAttr(ppd, q_keyword, NULL); + } + else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL) + q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); + + if (q1_attr && q1_attr->value && q1_attr->value[0]) + q1_choice = q1_attr->value; + else + q1_choice = ""; + + if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL && + attr->value && attr->value[0]) + { + snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); + q2_attr = ppdFindAttr(ppd, q_keyword, NULL); + } + else + q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL); + + if (q2_attr && q2_attr->value && q2_attr->value[0]) + q2_choice = q2_attr->value; + else + q2_choice = NULL; + + if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL && + attr->value && attr->value[0]) + { + snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); + q3_attr = ppdFindAttr(ppd, q_keyword, NULL); + } + else + q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL); + + if (q3_attr && q3_attr->value && q3_attr->value[0]) + q3_choice = q3_attr->value; + else + q3_choice = NULL; + } + +#ifdef __APPLE__ + /* + * Build the array of profiles... + * + * Note: This calloc actually requests slightly more memory than needed. + */ + + if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate memory for %d profiles!", + num_profiles); + ppdClose(ppd); + return; + } + + profiles->profileCount = num_profiles; + languages = _ppdGetLanguages(ppd); + profile = profiles->profiles; +#endif /* __APPLE__ */ + + for (attr = ppdFindAttr(ppd, profile_key, NULL); + attr; + attr = ppdFindNextAttr(ppd, profile_key, NULL)) + if (attr->spec[0] && attr->value && attr->value[0]) + { + /* + * Add this profile... + */ + + if (attr->value[0] != '/') + snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, + attr->value); + else + strlcpy(iccfile, attr->value, sizeof(iccfile)); + + if (access(iccfile, 0)) + continue; + +#ifdef __APPLE__ + if (profile_key[0] == 'c') + { + cupsArraySave(ppd->sorted_attrs); + + if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID", + attr->spec)) != NULL && + profileid_attr->value && isdigit(profileid_attr->value[0] & 255)) + profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10); + else + profile_id = _ppdHashName(attr->spec); + + cupsArrayRestore(ppd->sorted_attrs); + } + else + profile_id = atoi(attr->spec); + + apple_init_profile(ppd, languages, profile, profile_id, attr->spec, + attr->text[0] ? attr->text : attr->spec, iccfile); + profile ++; +#elif defined(HAVE_DBUS) + profile_id = attr->spec; + dbus_create_profile(profiles, con, p->name, attr->spec, iccfile); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + /* + * See if this is the default profile... + */ + + if (!default_profile_id) + { + if (q2_choice) + { + if (q3_choice) + { + snprintf(selector, sizeof(selector), "%s.%s.%s", + q1_choice, q2_choice, q3_choice); + if (!strcmp(selector, attr->spec)) + default_profile_id = profile_id; + } + + if (!default_profile_id) + { + snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, + q2_choice); + if (!strcmp(selector, attr->spec)) + default_profile_id = profile_id; + } + } + + if (!default_profile_id && q3_choice) + { + snprintf(selector, sizeof(selector), "%s..%s", q1_choice, + q3_choice); + if (!strcmp(selector, attr->spec)) + default_profile_id = profile_id; + } + + if (!default_profile_id) + { + snprintf(selector, sizeof(selector), "%s..", q1_choice); + if (!strcmp(selector, attr->spec)) + default_profile_id = profile_id; + } + } + } + +#ifdef __APPLE__ + _ppdFreeLanguages(languages); +#endif /* __APPLE__ */ + } + else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL) + { + /* + * Extract profiles from ColorModel option... + */ + + const char *profile_name; /* Name of generic profile */ + + + num_profiles = cm_option->num_choices; + +#ifdef __APPLE__ + if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate memory for %d profiles!", + num_profiles); + ppdClose(ppd); + return; + } + + profiles->profileCount = num_profiles; + profile = profiles->profiles; +#endif /* __APPLE__ */ + + for (i = cm_option->num_choices, cm_choice = cm_option->choices; + i > 0; + i --, cm_choice ++) + { + if (!strcmp(cm_choice->choice, "Gray") || + !strcmp(cm_choice->choice, "Black")) + profile_name = "Gray"; + else if (!strcmp(cm_choice->choice, "RGB") || + !strcmp(cm_choice->choice, "CMY")) + profile_name = "RGB"; + else if (!strcmp(cm_choice->choice, "CMYK") || + !strcmp(cm_choice->choice, "KCMY")) + profile_name = "CMYK"; + else + profile_name = "DeviceN"; + + snprintf(selector, sizeof(selector), "%s..", profile_name); + +#ifdef __APPLE__ + profile_id = _ppdHashName(selector); + apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice, + cm_choice->text, NULL); + profile ++; +#elif defined(HAVE_DBUS) + profile_id = selector; + dbus_create_profile(profiles, con, p->name, selector, NULL); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + if (cm_choice->marked) + default_profile_id = profile_id; + } + } + else + { + /* + * Use the default colorspace... + */ + + attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); + + num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2; + +#ifdef __APPLE__ + if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate memory for %d profiles!", + num_profiles); + ppdClose(ppd); + return; + } + + profiles->profileCount = num_profiles; + + apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."), + "Gray", "Gray", NULL); +#elif defined(HAVE_DBUS) + profile_id = "Gray.."; + dbus_create_profile(profiles, con, p->name, profile_id, NULL); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + switch (ppd->colorspace) + { + case PPD_CS_RGB : + case PPD_CS_CMY : +#ifdef __APPLE__ + apple_init_profile(ppd, NULL, profiles->profiles + 1, + _ppdHashName("RGB.."), "RGB", "RGB", NULL); +#elif defined(HAVE_DBUS) + profile_id = "RGB.."; + dbus_create_profile(profiles, con, p->name, profile_id, NULL); +#endif /* HAVE_DBUS */ + break; + case PPD_CS_RGBK : + case PPD_CS_CMYK : +#ifdef __APPLE__ + apple_init_profile(ppd, NULL, profiles->profiles + 1, + _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL); +#elif defined(HAVE_DBUS) + profile_id = "CMYK.."; + dbus_create_profile(profiles, con, p->name, profile_id, NULL); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + break; + + case PPD_CS_GRAY : + if (attr) + break; + + case PPD_CS_N : +#ifdef __APPLE__ + apple_init_profile(ppd, NULL, profiles->profiles + 1, + _ppdHashName("DeviceN.."), "DeviceN", "DeviceN", + NULL); +#elif defined(HAVE_DBUS) + profile_id = "DeviceN.."; + dbus_create_profile(profiles, con, p->name, profile_id, NULL); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + break; + } + } + + if (num_profiles > 0) + { + /* + * Make sure we have a default profile ID... + */ + + if (!default_profile_id) + { +#ifdef __APPLE__ + default_profile_id = profiles->profiles[num_profiles - 1].profileID; +#elif HAVE_DBUS + default_profile_id = profile_id; +#endif /* __APPLE__ */ + } + + /* + * Get the device ID hash and pathelogical name dictionary. + */ + + cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"", + p->name); + +#ifdef __APPLE__ + device_id = _ppdHashName(p->name); + + device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + printer_name = CFStringCreateWithCString(kCFAllocatorDefault, + p->name, kCFStringEncodingUTF8); + + if (device_name && printer_name) + { + CFDictionarySetValue(device_name, CFSTR("en"), printer_name); + + /* + * Register the device with ColorSync... + */ + + error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id, + device_name, &scope); + + /* + * Register the profiles... + */ + + if (error == noErr) + error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id, + default_profile_id, profiles); + } + else + error = 1000; +#elif defined(HAVE_DBUS) + dbus_create_device (con, p, profiles, default_profile_id); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + + /* + * Clean up... + */ + +#ifdef __APPLE__ + if (error != noErr) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to register ICC color profiles for \"%s\" - %d", + p->name, (int)error); + + for (profile = profiles->profiles; + num_profiles > 0; + profile ++, num_profiles --) + CFRelease(profile->profileName); + + free(profiles); + + if (printer_name) + CFRelease(printer_name); + + if (device_name) + CFRelease(device_name); +#elif defined(HAVE_DBUS) + for (profile_path = cupsArrayFirst(profiles); + profile_path; + profile_path = cupsArrayNext(profiles)) + free (profile_path); + + cupsArrayDelete(profiles); + dbus_connection_flush(con); + + /* + * Don't unref the connection but instead keep it around for future + * calls (it is a local static variable). Once we disconnect from + * the bus all our devices and profiles will be gone. + */ +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ + } + + ppdClose(ppd); +} + + +/* + * 'cupsdUnregisterColorProfiles()' - Remove color profiles for the specified + * printer. + */ + +void +cupsdUnregisterColorProfiles( + cupsd_printer_t *p) /* I - Printer */ +{ +#ifdef __APPLE__ + /* + * Make sure ColorSync is available... + */ + + if (CMUnregisterColorDevice != NULL) + CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name)); +#elif defined(HAVE_DBUS) + dbus_delete_device_and_profiles (p); +#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ +} + + /* * End of "$Id: printers.c 9313 2010-09-22 18:35:07Z mike $". */ diff -up cups-1.4.6/scheduler/printers.h.icc cups-1.4.6/scheduler/printers.h --- cups-1.4.6/scheduler/printers.h.icc 2011-01-12 16:12:56.348369195 +0000 +++ cups-1.4.6/scheduler/printers.h 2011-01-12 16:13:02.536065801 +0000 @@ -189,6 +189,8 @@ extern const char *cupsdValidateDest(con cups_ptype_t *dtype, cupsd_printer_t **printer); extern void cupsdWritePrintcap(void); +extern void cupsdRegisterColorProfiles(cupsd_printer_t *printer); +extern void cupsdUnregisterColorProfiles(cupsd_printer_t *printer); /*