Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/colorman.c
1090 views
1
/*
2
* Color management routines for the CUPS scheduler.
3
*
4
* Copyright © 2021-2022 by OpenPrinting.
5
* Copyright © 2007-2014 by Apple Inc.
6
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
7
*
8
* Licensed under Apache License v2.0. See the file "LICENSE" for more
9
* information.
10
*
11
* Original DBUS/colord code is Copyright © 2011 Red Hat, Inc.
12
*
13
* Redistribution and use in source and binary forms, with or without
14
* modification, are permitted provided that the following conditions
15
* are met:
16
*
17
* Redistributions of source code must retain the above copyright
18
* notice, this list of conditions and the following disclaimer.
19
*
20
* Redistributions in binary form must reproduce the above copyright
21
* notice, this list of conditions and the following disclaimer in the
22
* documentation and/or other materials provided with the distribution.
23
*
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35
* OF THE POSSIBILITY OF SUCH DAMAGE.
36
*/
37
38
/*
39
* Include necessary headers...
40
*/
41
42
#include "cupsd.h"
43
#include <cups/ppd-private.h>
44
45
#ifdef __APPLE__
46
# include <ApplicationServices/ApplicationServices.h>
47
extern CFUUIDRef ColorSyncCreateUUIDFromUInt32(unsigned id);
48
# include <CoreFoundation/CoreFoundation.h>
49
#elif defined(HAVE_DBUS)
50
# include <dbus/dbus.h>
51
52
/*
53
* Defines used by colord. See the reference docs for further details:
54
*
55
* http://colord.hughsie.com/api/ref-dbus.html
56
*/
57
58
# define COLORD_SCOPE_NORMAL "normal"
59
/* System scope */
60
# define COLORD_SCOPE_TEMP "temp" /* Process scope */
61
# define COLORD_SCOPE_DISK "disk" /* Lives forever, as stored in DB */
62
63
# define COLORD_RELATION_SOFT "soft" /* Mapping is not default */
64
# define COLORD_RELATION_HARD "hard" /* Explicitly mapped profile */
65
66
# define COLORD_SPACE_RGB "rgb" /* RGB colorspace */
67
# define COLORD_SPACE_CMYK "cmyk" /* CMYK colorspace */
68
# define COLORD_SPACE_GRAY "gray" /* Gray colorspace */
69
# define COLORD_SPACE_UNKNOWN "unknown"
70
/* Unknown colorspace */
71
72
# define COLORD_MODE_PHYSICAL "physical"
73
/* Actual device */
74
# define COLORD_MODE_VIRTUAL "virtual"
75
/* Virtual device with no hardware */
76
77
# define COLORD_KIND_PRINTER "printer"
78
/* printing output device */
79
80
# define COLORD_DBUS_SERVICE "org.freedesktop.ColorManager"
81
# define COLORD_DBUS_INTERFACE "org.freedesktop.ColorManager"
82
# define COLORD_DBUS_INTERFACE_DEVICE "org.freedesktop.ColorManager.Device"
83
# define COLORD_DBUS_PATH "/org/freedesktop/ColorManager"
84
/* Path for color management system */
85
# define COLORD_DBUS_TIMEOUT 5000 /* Timeout for connecting to colord in ms */
86
#endif /* __APPLE__ */
87
88
89
/*
90
* Local globals...
91
*/
92
93
#if !defined(__APPLE__) && defined(HAVE_DBUS)
94
static DBusConnection *colord_con = NULL;
95
/* DBUS connection for colord */
96
#endif /* !__APPLE__ && HAVE_DBUS */
97
98
99
/*
100
* Local functions...
101
*/
102
103
#ifdef __APPLE__
104
static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages,
105
CFMutableDictionaryRef profile,
106
unsigned id, const char *name,
107
const char *text, const char *iccfile);
108
static void apple_register_profiles(cupsd_printer_t *p);
109
static void apple_unregister_profiles(cupsd_printer_t *p);
110
111
#elif defined(HAVE_DBUS)
112
static void colord_create_device(cupsd_printer_t *p, ppd_file_t *ppd,
113
cups_array_t *profiles,
114
const char *colorspace, char **format,
115
const char *relation, const char *scope);
116
static void colord_create_profile(cups_array_t *profiles,
117
const char *printer_name,
118
const char *qualifier,
119
const char *colorspace,
120
char **format, const char *iccfile,
121
const char *scope);
122
static void colord_delete_device(const char *device_id);
123
static void colord_device_add_profile(const char *device_path,
124
const char *profile_path,
125
const char *relation);
126
static void colord_dict_add_strings(DBusMessageIter *dict,
127
const char *key, const char *value);
128
static char *colord_find_device(const char *device_id);
129
static void colord_get_qualifier_format(ppd_file_t *ppd, char *format[3]);
130
static void colord_register_printer(cupsd_printer_t *p);
131
static void colord_unregister_printer(cupsd_printer_t *p);
132
#endif /* __APPLE__ */
133
134
135
/*
136
* 'cupsdRegisterColor()' - Register vendor color profiles in a PPD file.
137
*/
138
139
void
140
cupsdRegisterColor(cupsd_printer_t *p) /* I - Printer */
141
{
142
#ifdef __APPLE__
143
if (!RunUser)
144
{
145
apple_unregister_profiles(p);
146
apple_register_profiles(p);
147
}
148
149
#elif defined(HAVE_DBUS)
150
if (!RunUser)
151
{
152
colord_unregister_printer(p);
153
colord_register_printer(p);
154
}
155
#endif /* __APPLE__ */
156
}
157
158
159
/*
160
* 'cupsdStartColor()' - Initialize color management.
161
*/
162
163
void
164
cupsdStartColor(void)
165
{
166
#if !defined(__APPLE__) && defined(HAVE_DBUS)
167
cupsd_printer_t *p; /* Current printer */
168
169
170
colord_con = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
171
172
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
173
p;
174
p = (cupsd_printer_t *)cupsArrayNext(Printers))
175
cupsdRegisterColor(p);
176
#endif /* !__APPLE__ && HAVE_DBUS */
177
}
178
179
180
/*
181
* 'cupsdStopColor()' - Shutdown color management.
182
*/
183
184
void
185
cupsdStopColor(void)
186
{
187
#if !defined(__APPLE__) && defined(HAVE_DBUS)
188
if (colord_con)
189
dbus_connection_unref(colord_con);
190
colord_con = NULL;
191
#endif /* !__APPLE__ && HAVE_DBUS */
192
}
193
194
195
/*
196
* 'cupsdUnregisterColor()' - Unregister vendor color profiles in a PPD file.
197
*/
198
199
void
200
cupsdUnregisterColor(cupsd_printer_t *p)/* I - Printer */
201
{
202
#ifdef __APPLE__
203
if (!RunUser)
204
apple_unregister_profiles(p);
205
206
#elif defined(HAVE_DBUS)
207
if (!RunUser)
208
colord_unregister_printer(p);
209
#endif /* __APPLE__ */
210
}
211
212
213
#ifdef __APPLE__
214
/*
215
* 'apple_init_profile()' - Initialize a color profile.
216
*/
217
218
static void
219
apple_init_profile(
220
ppd_file_t *ppd, /* I - PPD file */
221
cups_array_t *languages, /* I - Languages in the PPD file */
222
CFMutableDictionaryRef profile, /* I - Profile dictionary */
223
unsigned id, /* I - Profile ID */
224
const char *name, /* I - Profile name */
225
const char *text, /* I - Profile UI text */
226
const char *iccfile) /* I - ICC filename */
227
{
228
CFURLRef url; /* URL for profile filename */
229
CFMutableDictionaryRef dict; /* Dictionary for name */
230
char *language; /* Current language */
231
ppd_attr_t *attr; /* Profile attribute */
232
CFStringRef cflang, /* Language string */
233
cftext; /* Localized text */
234
235
236
(void)id;
237
238
/*
239
* Build the profile name dictionary...
240
*/
241
242
dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
243
&kCFTypeDictionaryKeyCallBacks,
244
&kCFTypeDictionaryValueCallBacks);
245
if (!dict)
246
{
247
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize profile \"%s\".",
248
iccfile);
249
return;
250
}
251
252
cftext = CFStringCreateWithCString(kCFAllocatorDefault, text,
253
kCFStringEncodingUTF8);
254
255
if (cftext)
256
{
257
CFDictionarySetValue(dict, CFSTR("en_US"), cftext);
258
CFRelease(cftext);
259
}
260
261
if (languages)
262
{
263
/*
264
* Find localized names for the color profiles...
265
*/
266
267
cupsArraySave(ppd->sorted_attrs);
268
269
for (language = (char *)cupsArrayFirst(languages);
270
language;
271
language = (char *)cupsArrayNext(languages))
272
{
273
if (iccfile)
274
{
275
if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name,
276
language)) == NULL)
277
attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language);
278
}
279
else
280
attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language);
281
282
if (attr && attr->text[0])
283
{
284
cflang = CFStringCreateWithCString(kCFAllocatorDefault, language,
285
kCFStringEncodingUTF8);
286
cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text,
287
kCFStringEncodingUTF8);
288
289
if (cflang && cftext)
290
CFDictionarySetValue(dict, cflang, cftext);
291
292
if (cflang)
293
CFRelease(cflang);
294
295
if (cftext)
296
CFRelease(cftext);
297
}
298
}
299
300
cupsArrayRestore(ppd->sorted_attrs);
301
}
302
303
/*
304
* Fill in the profile data...
305
*/
306
307
if (iccfile && *iccfile)
308
{
309
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)iccfile, (CFIndex)strlen(iccfile), false);
310
311
if (url)
312
{
313
CFDictionarySetValue(profile, kColorSyncDeviceProfileURL, url);
314
CFRelease(url);
315
}
316
}
317
318
CFDictionarySetValue(profile, kColorSyncDeviceModeDescriptions, dict);
319
CFRelease(dict);
320
}
321
322
323
/*
324
* 'apple_register_profiles()' - Register color profiles for a printer.
325
*/
326
327
static void
328
apple_register_profiles(
329
cupsd_printer_t *p) /* I - Printer */
330
{
331
int i; /* Looping var */
332
char ppdfile[1024], /* PPD filename */
333
iccfile[1024], /* ICC filename */
334
selector[PPD_MAX_NAME];
335
/* Profile selection string */
336
ppd_file_t *ppd; /* PPD file */
337
ppd_attr_t *attr, /* Profile attributes */
338
*profileid_attr,/* cupsProfileID attribute */
339
*q1_attr, /* ColorModel (or other) qualifier */
340
*q2_attr, /* MediaType (or other) qualifier */
341
*q3_attr; /* Resolution (or other) qualifier */
342
char q_keyword[PPD_MAX_NAME];
343
/* Qualifier keyword */
344
const char *q1_choice, /* ColorModel (or other) choice */
345
*q2_choice, /* MediaType (or other) choice */
346
*q3_choice; /* Resolution (or other) choice */
347
ppd_option_t *cm_option; /* Color model option */
348
ppd_choice_t *cm_choice; /* Color model choice */
349
int num_profiles; /* Number of profiles */
350
OSStatus error = 0; /* Last error */
351
unsigned device_id, /* Printer device ID */
352
profile_id = 0, /* Profile ID */
353
default_profile_id = 0;
354
/* Default profile ID */
355
CFMutableDictionaryRef device_name; /* Printer device name dictionary */
356
CFStringRef printer_name; /* Printer name string */
357
cups_array_t *languages; /* Languages array */
358
CFMutableDictionaryRef profiles, /* Dictionary of profiles */
359
profile; /* Current profile info dictionary */
360
CFStringRef dict_key; /* Key in factory profile dictionary */
361
362
363
/*
364
* Make sure ColorSync is available...
365
*/
366
367
if (&ColorSyncRegisterDevice == NULL)
368
return;
369
370
/*
371
* Try opening the PPD file for this printer...
372
*/
373
374
snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
375
if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL)
376
return;
377
378
/*
379
* See if we have any profiles...
380
*/
381
382
for (num_profiles = 0, attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
383
attr;
384
attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
385
if (attr->spec[0] && attr->value && attr->value[0])
386
{
387
if (attr->value[0] != '/')
388
snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
389
attr->value);
390
else
391
strlcpy(iccfile, attr->value, sizeof(iccfile));
392
393
if (access(iccfile, 0))
394
{
395
cupsdLogMessage(CUPSD_LOG_ERROR,
396
"%s: ICC Profile \"%s\" does not exist.", p->name,
397
iccfile);
398
cupsdSetPrinterReasons(p, "+cups-missing-filter-warning");
399
continue;
400
}
401
402
num_profiles ++;
403
}
404
405
/*
406
* Create a dictionary for the factory profiles...
407
*/
408
409
profiles = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
410
&kCFTypeDictionaryKeyCallBacks,
411
&kCFTypeDictionaryValueCallBacks);
412
if (!profiles)
413
{
414
cupsdLogMessage(CUPSD_LOG_ERROR,
415
"Unable to allocate memory for factory profiles.");
416
ppdClose(ppd);
417
return;
418
}
419
420
/*
421
* If we have profiles, add them...
422
*/
423
424
if (num_profiles > 0)
425
{
426
/*
427
* For CUPS PPDs, figure out the default profile selector values...
428
*/
429
430
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL &&
431
attr->value && attr->value[0])
432
{
433
snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
434
q1_attr = ppdFindAttr(ppd, q_keyword, NULL);
435
}
436
else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL)
437
q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
438
439
if (q1_attr && q1_attr->value && q1_attr->value[0])
440
q1_choice = q1_attr->value;
441
else
442
q1_choice = "";
443
444
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL &&
445
attr->value && attr->value[0])
446
{
447
snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
448
q2_attr = ppdFindAttr(ppd, q_keyword, NULL);
449
}
450
else
451
q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL);
452
453
if (q2_attr && q2_attr->value && q2_attr->value[0])
454
q2_choice = q2_attr->value;
455
else
456
q2_choice = NULL;
457
458
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL &&
459
attr->value && attr->value[0])
460
{
461
snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
462
q3_attr = ppdFindAttr(ppd, q_keyword, NULL);
463
}
464
else
465
q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL);
466
467
if (q3_attr && q3_attr->value && q3_attr->value[0])
468
q3_choice = q3_attr->value;
469
else
470
q3_choice = NULL;
471
472
/*
473
* Loop through the profiles listed in the PPD...
474
*/
475
476
languages = _ppdGetLanguages(ppd);
477
478
for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
479
attr;
480
attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
481
if (attr->spec[0] && attr->value && attr->value[0])
482
{
483
/*
484
* Add this profile...
485
*/
486
487
if (attr->value[0] != '/')
488
snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
489
attr->value);
490
else
491
strlcpy(iccfile, attr->value, sizeof(iccfile));
492
493
if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser,
494
cupsdLogFCMessage, p))
495
iccfile[0] = '\0';
496
497
cupsArraySave(ppd->sorted_attrs);
498
499
if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID",
500
attr->spec)) != NULL &&
501
profileid_attr->value && isdigit(profileid_attr->value[0] & 255))
502
profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10);
503
else
504
profile_id = _ppdHashName(attr->spec);
505
506
cupsArrayRestore(ppd->sorted_attrs);
507
508
profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
509
&kCFTypeDictionaryKeyCallBacks,
510
&kCFTypeDictionaryValueCallBacks);
511
if (!profile)
512
{
513
cupsdLogMessage(CUPSD_LOG_ERROR,
514
"Unable to allocate memory for color profile.");
515
CFRelease(profiles);
516
ppdClose(ppd);
517
return;
518
}
519
520
apple_init_profile(ppd, languages, profile, profile_id, attr->spec,
521
attr->text[0] ? attr->text : attr->spec, iccfile);
522
523
dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
524
CFSTR("%u"), profile_id);
525
if (dict_key)
526
{
527
CFDictionarySetValue(profiles, dict_key, profile);
528
CFRelease(dict_key);
529
}
530
531
CFRelease(profile);
532
533
/*
534
* See if this is the default profile...
535
*/
536
537
if (!default_profile_id && q1_choice && q2_choice && q3_choice)
538
{
539
snprintf(selector, sizeof(selector), "%s.%s.%s", q1_choice, q2_choice,
540
q3_choice);
541
if (!strcmp(selector, attr->spec))
542
default_profile_id = profile_id;
543
}
544
545
if (!default_profile_id && q1_choice && q2_choice)
546
{
547
snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, q2_choice);
548
if (!strcmp(selector, attr->spec))
549
default_profile_id = profile_id;
550
}
551
552
if (!default_profile_id && q1_choice && q3_choice)
553
{
554
snprintf(selector, sizeof(selector), "%s..%s", q1_choice, q3_choice);
555
if (!strcmp(selector, attr->spec))
556
default_profile_id = profile_id;
557
}
558
559
if (!default_profile_id && q1_choice)
560
{
561
snprintf(selector, sizeof(selector), "%s..", q1_choice);
562
if (!strcmp(selector, attr->spec))
563
default_profile_id = profile_id;
564
}
565
566
if (!default_profile_id && q2_choice && q3_choice)
567
{
568
snprintf(selector, sizeof(selector), ".%s.%s", q2_choice, q3_choice);
569
if (!strcmp(selector, attr->spec))
570
default_profile_id = profile_id;
571
}
572
573
if (!default_profile_id && q2_choice)
574
{
575
snprintf(selector, sizeof(selector), ".%s.", q2_choice);
576
if (!strcmp(selector, attr->spec))
577
default_profile_id = profile_id;
578
}
579
580
if (!default_profile_id && q3_choice)
581
{
582
snprintf(selector, sizeof(selector), "..%s", q3_choice);
583
if (!strcmp(selector, attr->spec))
584
default_profile_id = profile_id;
585
}
586
}
587
588
_ppdFreeLanguages(languages);
589
}
590
else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL)
591
{
592
/*
593
* Extract profiles from ColorModel option...
594
*/
595
596
const char *profile_name; /* Name of generic profile */
597
598
599
num_profiles = cm_option->num_choices;
600
601
for (i = cm_option->num_choices, cm_choice = cm_option->choices;
602
i > 0;
603
i --, cm_choice ++)
604
{
605
if (!strcmp(cm_choice->choice, "Gray") ||
606
!strcmp(cm_choice->choice, "Black"))
607
profile_name = "Gray";
608
else if (!strcmp(cm_choice->choice, "RGB") ||
609
!strcmp(cm_choice->choice, "CMY"))
610
profile_name = "RGB";
611
else if (!strcmp(cm_choice->choice, "CMYK") ||
612
!strcmp(cm_choice->choice, "KCMY"))
613
profile_name = "CMYK";
614
else
615
profile_name = "DeviceN";
616
617
snprintf(selector, sizeof(selector), "%s..", profile_name);
618
profile_id = _ppdHashName(selector);
619
620
profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
621
&kCFTypeDictionaryKeyCallBacks,
622
&kCFTypeDictionaryValueCallBacks);
623
if (!profile)
624
{
625
cupsdLogMessage(CUPSD_LOG_ERROR,
626
"Unable to allocate memory for color profile.");
627
CFRelease(profiles);
628
ppdClose(ppd);
629
return;
630
}
631
632
apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice,
633
cm_choice->text, NULL);
634
635
dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
636
CFSTR("%u"), profile_id);
637
if (dict_key)
638
{
639
CFDictionarySetValue(profiles, dict_key, profile);
640
CFRelease(dict_key);
641
}
642
643
CFRelease(profile);
644
645
if (cm_choice->marked)
646
default_profile_id = profile_id;
647
}
648
}
649
else
650
{
651
/*
652
* Use the default colorspace...
653
*/
654
655
attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
656
657
num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2;
658
659
/*
660
* Add the grayscale profile first. We always have a grayscale profile.
661
*/
662
663
profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
664
&kCFTypeDictionaryKeyCallBacks,
665
&kCFTypeDictionaryValueCallBacks);
666
667
if (!profile)
668
{
669
cupsdLogMessage(CUPSD_LOG_ERROR,
670
"Unable to allocate memory for color profile.");
671
CFRelease(profiles);
672
ppdClose(ppd);
673
return;
674
}
675
676
profile_id = _ppdHashName("Gray..");
677
apple_init_profile(ppd, NULL, profile, profile_id, "Gray", "Gray", NULL);
678
679
dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"),
680
profile_id);
681
if (dict_key)
682
{
683
CFDictionarySetValue(profiles, dict_key, profile);
684
CFRelease(dict_key);
685
}
686
687
CFRelease(profile);
688
689
/*
690
* Then add the RGB/CMYK/DeviceN color profile...
691
*/
692
693
profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
694
&kCFTypeDictionaryKeyCallBacks,
695
&kCFTypeDictionaryValueCallBacks);
696
697
if (!profile)
698
{
699
cupsdLogMessage(CUPSD_LOG_ERROR,
700
"Unable to allocate memory for color profile.");
701
CFRelease(profiles);
702
ppdClose(ppd);
703
return;
704
}
705
706
switch (ppd->colorspace)
707
{
708
default :
709
case PPD_CS_RGB :
710
case PPD_CS_CMY :
711
profile_id = _ppdHashName("RGB..");
712
apple_init_profile(ppd, NULL, profile, profile_id, "RGB", "RGB",
713
NULL);
714
break;
715
716
case PPD_CS_RGBK :
717
case PPD_CS_CMYK :
718
profile_id = _ppdHashName("CMYK..");
719
apple_init_profile(ppd, NULL, profile, profile_id, "CMYK", "CMYK",
720
NULL);
721
break;
722
723
case PPD_CS_GRAY :
724
if (attr)
725
break;
726
727
case PPD_CS_N :
728
profile_id = _ppdHashName("DeviceN..");
729
apple_init_profile(ppd, NULL, profile, profile_id, "DeviceN",
730
"DeviceN", NULL);
731
break;
732
}
733
734
if (CFDictionaryGetCount(profile) > 0)
735
{
736
dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
737
CFSTR("%u"), profile_id);
738
if (dict_key)
739
{
740
CFDictionarySetValue(profiles, dict_key, profile);
741
CFRelease(dict_key);
742
}
743
}
744
745
CFRelease(profile);
746
}
747
748
if (num_profiles > 0)
749
{
750
/*
751
* Make sure we have a default profile ID...
752
*/
753
754
if (!default_profile_id)
755
default_profile_id = profile_id; /* Last profile */
756
757
dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"),
758
default_profile_id);
759
if (dict_key)
760
{
761
CFDictionarySetValue(profiles, kColorSyncDeviceDefaultProfileID,
762
dict_key);
763
CFRelease(dict_key);
764
}
765
766
/*
767
* Get the device ID hash and pathelogical name dictionary.
768
*/
769
770
cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
771
p->name);
772
773
device_id = _ppdHashName(p->name);
774
device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
775
&kCFTypeDictionaryKeyCallBacks,
776
&kCFTypeDictionaryValueCallBacks);
777
printer_name = CFStringCreateWithCString(kCFAllocatorDefault,
778
p->name, kCFStringEncodingUTF8);
779
780
if (device_name && printer_name)
781
{
782
/*
783
* Register the device with ColorSync...
784
*/
785
786
CFTypeRef deviceDictKeys[] =
787
{ /* Device keys */
788
kColorSyncDeviceDescriptions,
789
kColorSyncFactoryProfiles,
790
kColorSyncDeviceUserScope,
791
kColorSyncDeviceHostScope
792
};
793
CFTypeRef deviceDictVals[] =
794
{ /* Device values */
795
device_name,
796
profiles,
797
kCFPreferencesAnyUser,
798
kCFPreferencesCurrentHost
799
};
800
CFDictionaryRef deviceDict; /* Device dictionary */
801
CFUUIDRef deviceUUID; /* Device UUID */
802
803
CFDictionarySetValue(device_name, CFSTR("en_US"), printer_name);
804
805
deviceDict = CFDictionaryCreate(kCFAllocatorDefault,
806
(const void **)deviceDictKeys,
807
(const void **)deviceDictVals,
808
sizeof(deviceDictKeys) /
809
sizeof(deviceDictKeys[0]),
810
&kCFTypeDictionaryKeyCallBacks,
811
&kCFTypeDictionaryValueCallBacks);
812
deviceUUID = ColorSyncCreateUUIDFromUInt32(device_id);
813
814
if (!deviceDict || !deviceUUID ||
815
!ColorSyncRegisterDevice(kColorSyncPrinterDeviceClass, deviceUUID,
816
deviceDict))
817
error = 1001;
818
819
if (deviceUUID)
820
CFRelease(deviceUUID);
821
822
if (deviceDict)
823
CFRelease(deviceDict);
824
}
825
else
826
error = 1000;
827
828
/*
829
* Clean up...
830
*/
831
832
if (error != noErr)
833
cupsdLogMessage(CUPSD_LOG_ERROR,
834
"Unable to register ICC color profiles for \"%s\": %d",
835
p->name, (int)error);
836
837
if (printer_name)
838
CFRelease(printer_name);
839
840
if (device_name)
841
CFRelease(device_name);
842
}
843
844
/*
845
* Free any memory we used...
846
*/
847
848
CFRelease(profiles);
849
850
ppdClose(ppd);
851
}
852
853
854
/*
855
* 'apple_unregister_profiles()' - Remove color profiles for the specified
856
* printer.
857
*/
858
859
static void
860
apple_unregister_profiles(
861
cupsd_printer_t *p) /* I - Printer */
862
{
863
/*
864
* Make sure ColorSync is available...
865
*/
866
867
if (&ColorSyncUnregisterDevice != NULL)
868
{
869
CFUUIDRef deviceUUID; /* Device UUID */
870
871
deviceUUID = ColorSyncCreateUUIDFromUInt32(_ppdHashName(p->name));
872
if (deviceUUID)
873
{
874
ColorSyncUnregisterDevice(kColorSyncPrinterDeviceClass, deviceUUID);
875
CFRelease(deviceUUID);
876
}
877
}
878
}
879
880
881
#elif defined(HAVE_DBUS)
882
/*
883
* 'colord_create_device()' - Create a device and register profiles.
884
*/
885
886
static void
887
colord_create_device(
888
cupsd_printer_t *p, /* I - Printer */
889
ppd_file_t *ppd, /* I - PPD file */
890
cups_array_t *profiles, /* I - Profiles array */
891
const char *colorspace, /* I - Device colorspace, e.g. 'rgb' */
892
char **format, /* I - Device qualifier format */
893
const char *relation, /* I - Profile relation, either 'soft'
894
or 'hard' */
895
const char *scope) /* I - The scope of the device, e.g.
896
'normal', 'temp' or 'disk' */
897
{
898
DBusMessage *message = NULL; /* D-Bus request */
899
DBusMessage *reply = NULL; /* D-Bus reply */
900
DBusMessageIter args; /* D-Bus method arguments */
901
DBusMessageIter dict; /* D-Bus method arguments */
902
DBusError error; /* D-Bus error */
903
const char *device_path; /* Device object path */
904
const char *profile_path; /* Profile path */
905
char device_id[1024]; /* Device ID as understood by colord */
906
char format_str[1024]; /* Qualifier format as a string */
907
908
909
/*
910
* Create the device...
911
*/
912
913
snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
914
device_path = device_id;
915
916
message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
917
COLORD_DBUS_PATH,
918
COLORD_DBUS_INTERFACE,
919
"CreateDevice");
920
921
dbus_message_iter_init_append(message, &args);
922
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_path);
923
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
924
925
snprintf(format_str, sizeof(format_str), "%s.%s.%s", format[0], format[1],
926
format[2]);
927
928
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{ss}", &dict);
929
colord_dict_add_strings(&dict, "Colorspace", colorspace);
930
colord_dict_add_strings(&dict, "Mode", COLORD_MODE_PHYSICAL);
931
if (ppd->manufacturer)
932
colord_dict_add_strings(&dict, "Vendor", ppd->manufacturer);
933
if (ppd->modelname)
934
colord_dict_add_strings(&dict, "Model", ppd->modelname);
935
if (p->sanitized_device_uri)
936
colord_dict_add_strings(&dict, "Serial", p->sanitized_device_uri);
937
colord_dict_add_strings(&dict, "Format", format_str);
938
colord_dict_add_strings(&dict, "Kind", COLORD_KIND_PRINTER);
939
dbus_message_iter_close_container(&args, &dict);
940
941
/*
942
* Send the CreateDevice request synchronously...
943
*/
944
945
dbus_error_init(&error);
946
cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%s)", device_id,
947
scope);
948
reply = dbus_connection_send_with_reply_and_block(colord_con, message,
949
COLORD_DBUS_TIMEOUT,
950
&error);
951
if (!reply)
952
{
953
cupsdLogMessage(CUPSD_LOG_WARN, "CreateDevice failed: %s:%s", error.name,
954
error.message);
955
dbus_error_free(&error);
956
goto out;
957
}
958
959
/*
960
* Get reply data...
961
*/
962
963
dbus_message_iter_init(reply, &args);
964
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
965
{
966
cupsdLogMessage(CUPSD_LOG_WARN,
967
"CreateDevice failed: Incorrect reply type.");
968
goto out;
969
}
970
971
dbus_message_iter_get_basic(&args, &device_path);
972
cupsdLogMessage(CUPSD_LOG_DEBUG, "Created device \"%s\".", device_path);
973
974
/*
975
* Add profiles...
976
*/
977
978
for (profile_path = cupsArrayFirst(profiles);
979
profile_path;
980
profile_path = cupsArrayNext(profiles))
981
{
982
colord_device_add_profile(device_path, profile_path, relation);
983
}
984
985
out:
986
987
if (message)
988
dbus_message_unref(message);
989
990
if (reply)
991
dbus_message_unref(reply);
992
}
993
994
995
/*
996
* 'colord_create_profile()' - Create a color profile for a printer.
997
*/
998
999
static void
1000
colord_create_profile(
1001
cups_array_t *profiles, /* I - Profiles array */
1002
const char *printer_name, /* I - Printer name */
1003
const char *qualifier, /* I - Profile qualifier */
1004
const char *colorspace, /* I - Profile colorspace */
1005
char **format, /* I - Profile qualifier format */
1006
const char *iccfile, /* I - ICC filename */
1007
const char *scope) /* I - The scope of the profile, e.g.
1008
'normal', 'temp' or 'disk' */
1009
{
1010
DBusMessage *message = NULL; /* D-Bus request */
1011
DBusMessage *reply = NULL; /* D-Bus reply */
1012
DBusMessageIter args; /* D-Bus method arguments */
1013
DBusMessageIter dict; /* D-Bus method arguments */
1014
DBusError error; /* D-Bus error */
1015
char *idstr; /* Profile ID string */
1016
size_t idstrlen; /* Profile ID allocated length */
1017
const char *profile_path; /* Device object path */
1018
char format_str[1024]; /* Qualifier format as a string */
1019
1020
1021
/*
1022
* Create the profile...
1023
*/
1024
1025
message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1026
COLORD_DBUS_PATH,
1027
COLORD_DBUS_INTERFACE,
1028
"CreateProfile");
1029
1030
idstrlen = strlen(printer_name) + 1 + strlen(qualifier) + 1;
1031
if ((idstr = malloc(idstrlen)) == NULL)
1032
goto out;
1033
snprintf(idstr, idstrlen, "%s-%s", printer_name, qualifier);
1034
cupsdLogMessage(CUPSD_LOG_DEBUG, "Using profile ID \"%s\".", idstr);
1035
1036
dbus_message_iter_init_append(message, &args);
1037
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &idstr);
1038
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
1039
1040
snprintf(format_str, sizeof(format_str), "%s.%s.%s", format[0], format[1],
1041
format[2]);
1042
1043
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{ss}", &dict);
1044
colord_dict_add_strings(&dict, "Qualifier", qualifier);
1045
colord_dict_add_strings(&dict, "Format", format_str);
1046
colord_dict_add_strings(&dict, "Colorspace", colorspace);
1047
if (iccfile)
1048
colord_dict_add_strings(&dict, "Filename", iccfile);
1049
dbus_message_iter_close_container(&args, &dict);
1050
1051
/*
1052
* Send the CreateProfile request synchronously...
1053
*/
1054
1055
dbus_error_init(&error);
1056
cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%s)", idstr,
1057
scope);
1058
reply = dbus_connection_send_with_reply_and_block(colord_con, message,
1059
COLORD_DBUS_TIMEOUT,
1060
&error);
1061
if (!reply)
1062
{
1063
cupsdLogMessage(CUPSD_LOG_WARN, "CreateProfile failed: %s:%s", error.name,
1064
error.message);
1065
dbus_error_free(&error);
1066
goto out;
1067
}
1068
1069
/*
1070
* Get reply data...
1071
*/
1072
1073
dbus_message_iter_init(reply, &args);
1074
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
1075
{
1076
cupsdLogMessage(CUPSD_LOG_WARN,
1077
"CreateProfile failed: Incorrect reply type.");
1078
goto out;
1079
}
1080
1081
dbus_message_iter_get_basic(&args, &profile_path);
1082
cupsdLogMessage(CUPSD_LOG_DEBUG, "Created profile \"%s\".", profile_path);
1083
cupsArrayAdd(profiles, strdup(profile_path));
1084
1085
out:
1086
1087
if (message)
1088
dbus_message_unref(message);
1089
1090
if (reply)
1091
dbus_message_unref(reply);
1092
1093
if (idstr)
1094
free(idstr);
1095
}
1096
1097
1098
/*
1099
* 'colord_delete_device()' - Delete a device
1100
*/
1101
1102
static void
1103
colord_delete_device(
1104
const char *device_id) /* I - Device ID string */
1105
{
1106
DBusMessage *message = NULL; /* D-Bus request */
1107
DBusMessage *reply = NULL; /* D-Bus reply */
1108
DBusMessageIter args; /* D-Bus method arguments */
1109
DBusError error; /* D-Bus error */
1110
char *device_path; /* Device object path */
1111
1112
1113
/*
1114
* Find the device...
1115
*/
1116
1117
if ((device_path = colord_find_device(device_id)) == NULL)
1118
goto out;
1119
1120
/*
1121
* Delete the device...
1122
*/
1123
1124
message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1125
COLORD_DBUS_PATH,
1126
COLORD_DBUS_INTERFACE,
1127
"DeleteDevice");
1128
1129
dbus_message_iter_init_append(message, &args);
1130
dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &device_path);
1131
1132
/*
1133
* Send the DeleteDevice request synchronously...
1134
*/
1135
1136
dbus_error_init(&error);
1137
cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling DeleteDevice(%s)", device_path);
1138
reply = dbus_connection_send_with_reply_and_block(colord_con, message,
1139
COLORD_DBUS_TIMEOUT,
1140
&error);
1141
if (!reply)
1142
{
1143
cupsdLogMessage(CUPSD_LOG_DEBUG, "DeleteDevice failed: %s:%s", error.name,
1144
error.message);
1145
dbus_error_free(&error);
1146
goto out;
1147
}
1148
1149
out:
1150
1151
if (device_path)
1152
free(device_path);
1153
1154
if (message)
1155
dbus_message_unref(message);
1156
1157
if (reply)
1158
dbus_message_unref(reply);
1159
}
1160
1161
1162
/*
1163
* 'colord_device_add_profile()' - Assign a profile to a device.
1164
*/
1165
1166
static void
1167
colord_device_add_profile(
1168
const char *device_path, /* I - Device object path */
1169
const char *profile_path, /* I - Profile object path */
1170
const char *relation) /* I - Device relation, either
1171
'soft' or 'hard' */
1172
{
1173
DBusMessage *message = NULL; /* D-Bus request */
1174
DBusMessage *reply = NULL; /* D-Bus reply */
1175
DBusMessageIter args; /* D-Bus method arguments */
1176
DBusError error; /* D-Bus error */
1177
1178
1179
message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1180
device_path,
1181
COLORD_DBUS_INTERFACE_DEVICE,
1182
"AddProfile");
1183
1184
dbus_message_iter_init_append(message, &args);
1185
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &relation);
1186
dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &profile_path);
1187
cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling %s:AddProfile(%s) [%s]",
1188
device_path, profile_path, relation);
1189
1190
/*
1191
* Send the AddProfile request synchronously...
1192
*/
1193
1194
dbus_error_init(&error);
1195
reply = dbus_connection_send_with_reply_and_block(colord_con, message,
1196
COLORD_DBUS_TIMEOUT,
1197
&error);
1198
if (!reply)
1199
{
1200
cupsdLogMessage(CUPSD_LOG_WARN, "AddProfile failed: %s:%s", error.name,
1201
error.message);
1202
dbus_error_free(&error);
1203
goto out;
1204
}
1205
1206
out:
1207
1208
if (message)
1209
dbus_message_unref(message);
1210
1211
if (reply)
1212
dbus_message_unref(reply);
1213
}
1214
1215
1216
/*
1217
* 'colord_dict_add_strings()' - Add two strings to a dictionary.
1218
*/
1219
1220
static void
1221
colord_dict_add_strings(
1222
DBusMessageIter *dict, /* I - Dictionary */
1223
const char *key, /* I - Key string */
1224
const char *value) /* I - Value string */
1225
{
1226
DBusMessageIter entry; /* Entry to add */
1227
1228
1229
dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
1230
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1231
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
1232
dbus_message_iter_close_container(dict, &entry);
1233
}
1234
1235
1236
/*
1237
* 'colord_find_device()' - Finds a device
1238
*/
1239
1240
static char * /* O - Device path or NULL */
1241
colord_find_device(
1242
const char *device_id) /* I - Device ID string */
1243
{
1244
DBusMessage *message = NULL; /* D-Bus request */
1245
DBusMessage *reply = NULL; /* D-Bus reply */
1246
DBusMessageIter args; /* D-Bus method arguments */
1247
DBusError error; /* D-Bus error */
1248
const char *device_path_tmp; /* Device object path */
1249
char *device_path = NULL; /* Device object path */
1250
1251
1252
message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1253
COLORD_DBUS_PATH,
1254
COLORD_DBUS_INTERFACE,
1255
"FindDeviceById");
1256
1257
dbus_message_iter_init_append(message, &args);
1258
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
1259
1260
/*
1261
* Send the FindDeviceById request synchronously...
1262
*/
1263
1264
dbus_error_init(&error);
1265
cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById(%s)", device_id);
1266
reply = dbus_connection_send_with_reply_and_block(colord_con, message,
1267
COLORD_DBUS_TIMEOUT,
1268
&error);
1269
if (!reply)
1270
{
1271
cupsdLogMessage(CUPSD_LOG_DEBUG, "FindDeviceById failed: %s:%s",
1272
error.name, error.message);
1273
dbus_error_free(&error);
1274
goto out;
1275
}
1276
1277
/*
1278
* Get reply data...
1279
*/
1280
1281
dbus_message_iter_init(reply, &args);
1282
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
1283
{
1284
cupsdLogMessage(CUPSD_LOG_WARN,
1285
"FindDeviceById failed: Incorrect reply type.");
1286
goto out;
1287
}
1288
1289
dbus_message_iter_get_basic(&args, &device_path_tmp);
1290
if (device_path_tmp)
1291
device_path = strdup(device_path_tmp);
1292
1293
out:
1294
1295
if (message)
1296
dbus_message_unref(message);
1297
1298
if (reply)
1299
dbus_message_unref(reply);
1300
1301
return (device_path);
1302
}
1303
1304
1305
/*
1306
* 'colord_get_qualifier_format()' - Get the qualifier format.
1307
*
1308
* Note: Returns a value of "ColorSpace.MediaType.Resolution" by default.
1309
*/
1310
1311
static void
1312
colord_get_qualifier_format(
1313
ppd_file_t *ppd, /* I - PPD file data */
1314
char *format[3]) /* I - Format tuple */
1315
{
1316
const char *tmp; /* Temporary string */
1317
ppd_attr_t *attr; /* Profile attributes */
1318
1319
1320
/*
1321
* Get 1st section...
1322
*/
1323
1324
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL)
1325
tmp = attr->value;
1326
else if (ppdFindAttr(ppd, "DefaultColorModel", NULL))
1327
tmp = "ColorModel";
1328
else if (ppdFindAttr(ppd, "DefaultColorSpace", NULL))
1329
tmp = "ColorSpace";
1330
else
1331
tmp = "";
1332
1333
format[0] = strdup(tmp);
1334
1335
/*
1336
* Get 2nd section...
1337
*/
1338
1339
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL)
1340
tmp = attr->value;
1341
else
1342
tmp = "MediaType";
1343
1344
format[1] = strdup(tmp);
1345
1346
/*
1347
* Get 3rd section...
1348
*/
1349
1350
if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL)
1351
tmp = attr->value;
1352
else
1353
tmp = "Resolution";
1354
1355
format[2] = strdup(tmp);
1356
}
1357
1358
1359
/*
1360
* 'colord_register_printer()' - Register profiles for a printer.
1361
*/
1362
1363
static void
1364
colord_register_printer(
1365
cupsd_printer_t *p) /* I - printer */
1366
{
1367
char ppdfile[1024], /* PPD filename */
1368
iccfile[1024]; /* ICC filename */
1369
ppd_file_t *ppd; /* PPD file */
1370
cups_array_t *profiles; /* Profile paths array */
1371
ppd_attr_t *attr; /* Profile attributes */
1372
const char *device_colorspace; /* Device colorspace */
1373
char *format[3]; /* Qualifier format tuple */
1374
1375
1376
/*
1377
* Ensure we have a D-Bus connection...
1378
*/
1379
1380
if (!colord_con)
1381
return;
1382
1383
/*
1384
* Try opening the PPD file for this printer...
1385
*/
1386
1387
snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
1388
if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL)
1389
return;
1390
1391
/*
1392
* Find out the qualifier format
1393
*/
1394
1395
colord_get_qualifier_format(ppd, format);
1396
1397
/*
1398
* See if we have any embedded profiles...
1399
*/
1400
1401
profiles = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup,
1402
(cups_afree_func_t)free);
1403
for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
1404
attr;
1405
attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
1406
if (attr->spec[0] && attr->value && attr->value[0])
1407
{
1408
if (attr->value[0] != '/')
1409
snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
1410
attr->value);
1411
else
1412
strlcpy(iccfile, attr->value, sizeof(iccfile));
1413
1414
if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser,
1415
cupsdLogFCMessage, p))
1416
continue;
1417
1418
colord_create_profile(profiles, p->name, attr->spec, COLORD_SPACE_UNKNOWN,
1419
format, iccfile, COLORD_SCOPE_TEMP);
1420
}
1421
1422
/*
1423
* Add the grayscale profile first. We always have a grayscale profile.
1424
*/
1425
1426
colord_create_profile(profiles, p->name, "Gray..", COLORD_SPACE_GRAY,
1427
format, NULL, COLORD_SCOPE_TEMP);
1428
1429
/*
1430
* Then add the RGB/CMYK/DeviceN color profile...
1431
*/
1432
1433
device_colorspace = "unknown";
1434
switch (ppd->colorspace)
1435
{
1436
case PPD_CS_RGB :
1437
case PPD_CS_CMY :
1438
device_colorspace = COLORD_SPACE_RGB;
1439
colord_create_profile(profiles, p->name, "RGB..", COLORD_SPACE_RGB,
1440
format, NULL, COLORD_SCOPE_TEMP);
1441
break;
1442
1443
case PPD_CS_RGBK :
1444
case PPD_CS_CMYK :
1445
device_colorspace = COLORD_SPACE_CMYK;
1446
colord_create_profile(profiles, p->name, "CMYK..", COLORD_SPACE_CMYK,
1447
format, NULL, COLORD_SCOPE_TEMP);
1448
break;
1449
1450
case PPD_CS_GRAY :
1451
device_colorspace = COLORD_SPACE_GRAY;
1452
break;
1453
1454
case PPD_CS_N :
1455
colord_create_profile(profiles, p->name, "DeviceN..",
1456
COLORD_SPACE_UNKNOWN, format, NULL,
1457
COLORD_SCOPE_TEMP);
1458
break;
1459
}
1460
1461
/*
1462
* Register the device with colord.
1463
*/
1464
1465
cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\".",
1466
p->name);
1467
colord_create_device(p, ppd, profiles, device_colorspace, format,
1468
COLORD_RELATION_SOFT, COLORD_SCOPE_TEMP);
1469
1470
/*
1471
* Free any memory we used...
1472
*/
1473
1474
cupsArrayDelete(profiles);
1475
1476
free(format[0]);
1477
free(format[1]);
1478
free(format[2]);
1479
1480
ppdClose(ppd);
1481
}
1482
1483
1484
/*
1485
* 'colord_unregister_printer()' - Unregister profiles for a printer.
1486
*/
1487
1488
static void
1489
colord_unregister_printer(
1490
cupsd_printer_t *p) /* I - printer */
1491
{
1492
char device_id[1024]; /* Device ID as understood by colord */
1493
1494
1495
/*
1496
* Ensure we have a D-Bus connection...
1497
*/
1498
1499
if (!colord_con)
1500
return;
1501
1502
/*
1503
* Just delete the device itself, and leave the profiles registered
1504
*/
1505
1506
snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
1507
colord_delete_device(device_id);
1508
}
1509
#endif /* __APPLE__ */
1510
1511