From: Michael R Sweet Date: Thu, 25 Apr 2024 22:16:21 +0000 (-0400) Subject: Add job-presets-supported to CUPS shared printers (Issue #778) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3584de33505d76befdfddc0841b020e448a52118;p=thirdparty%2Fcups.git Add job-presets-supported to CUPS shared printers (Issue #778) --- diff --git a/CHANGES.md b/CHANGES.md index 55653181a6..501cf1da7d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Changes in CUPS v2.5b1 (TBA) - Added support for wide-area DNS-SD with Avahi (Issue #319) - Added `cupsCopyDestInfo2` API (Issue #586) - Added OpenSSL support for `cupsHashData` (Issue #762) +- Added "job-presets-supported" support for CUPS shared printers (Issue #778) - Added warning if the device has to do IPP request for 'all,media-col-database' in separate requests (Issue #829) - Added a new argument value for `lpstat` argument '-W' - `successful` - diff --git a/cups/ipp-support.c b/cups/ipp-support.c index 830380e32c..29fc0b11e3 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -1666,14 +1666,14 @@ ippCreateRequestedArray(ipp_t *request) // I - IPP request "job-page-limit", // CUPS extension "job-password-encryption-supported", "job-password-supported", - "job-presets-supported", // IPP Presets + "job-presets-supported", // IPP Driver Replacement Extensions "job-privacy-attributes", // IPP Privacy Attributes "job-privacy-scope", // IPP Privacy Attributes "job-quota-period", // CUPS extension - "job-resolvers-supported", + "job-resolvers-supported", // IPP Driver Replacement Extensions "job-settable-attributes-supported", "job-spooling-supported", - "job-triggers-supported", // IPP Presets + "job-triggers-supported", // IPP Driver Replacement Extensions "jpeg-k-octets-supported", // CUPS extension "jpeg-x-dimension-supported", // CUPS extension "jpeg-y-dimension-supported", // CUPS extension diff --git a/scheduler/printers.c b/scheduler/printers.c index fe93224d1f..a70b51bb99 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -4084,6 +4084,131 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ "job-password-supported", (int)strlen(p->pc->password)); } + // job-presets-supported + for (attr = NULL, ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL); ppd_attr; ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) + { + ipp_t *col = ippNew();// job-presets-supported value + cups_array_t *preset = cupsArrayNewStrings(ppd_attr->value, ' '); + // Preset values + const char *name, *value; // Option name and value + pwg_media_t *media = NULL; // media-size + const char *source = NULL, // media-source + *type = NULL; // media-type + + // Add preset attributes... + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_NAME, "preset-name", NULL, ppd_attr->spec); + + for (name = (const char *)cupsArrayGetFirst(preset), num_finishings = 0; name; name = (const char *)cupsArrayGetNext(preset)) + { + // Skip categories + if (*name != '*') + continue; + + // Get value for option... + if ((value = (const char *)cupsArrayGetNext(preset)) == NULL) + break; + + // Map it to IPP... + if (!strcmp(name, "*Booklet") && num_finishings < (int)(sizeof(finishings) / sizeof(finishings[0]))) + { + finishings[num_finishings ++] = IPP_FINISHINGS_BOOKLET_MAKER; + } + else if ((!strcmp(name, "*FoldType") || !strcmp(name, "*PunchMedia") || !strcmp(name, "*StapleLocation")) && num_finishings < (int)(sizeof(finishings) / sizeof(finishings[0]))) + { + finishings[num_finishings ++] = ippEnumValue("finishings", value); + } + else if (!strcmp(name, "*cupsFinishingTemplate")) + { + ipp_t *finishings_col = ippNew(); + + ippAddString(finishings_col, IPP_TAG_ZERO, strchr(value, ' ') != NULL || isupper(*value & 255) ? IPP_TAG_NAME : IPP_TAG_KEYWORD, "finishing-template", NULL, value); + ippAddCollection(col, IPP_TAG_ZERO, "finishings-col", finishings_col); + ippDelete(finishings_col); + } + else if (!strcmp(name, "*OutputBin")) + { + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "output-bin", NULL, _ppdCacheGetBin(p->pc, value)); + } + else if (!strcmp(name, "*InputSlot")) + { + source = value; + } + else if (!strcmp(name, "*MediaType")) + { + type = value; + } + else if (!strcmp(name, "*PageSize")) + { + media = pwgMediaForPPD(value); + } + else if (!strcmp(name, "*cupsPrintQuality")) + { + if (!strcmp(value, "Draft")) + ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_DRAFT); + else if (!strcmp(value, "High")) + ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_HIGH); + else + ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_NORMAL); + } + else if (!strcmp(name, "Duplex")) + { + if (!strcmp(value, "None")) + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "sides", NULL, "one-sided"); + else if (!strcmp(value, "DuplexNoTumble")) + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-long-edge"); + else if (!strcmp(value, "DuplexTumble")) + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-short-edge"); + } + else + { + // Something else... + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, name, NULL, value); + } + } + + if (num_finishings > 0) + ippAddIntegers(col, IPP_TAG_ZERO, IPP_TAG_ENUM, "finishings", num_finishings, finishings); + + if (media || source || type) + { + if (!source && !type) + { + // Just media size + ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media", NULL, media->pwg); + } + else + { + // Size, source, and/or type + ipp_t *media_col = ippNew(); + ipp_t *media_size = ippNew(); + + ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", media->width); + ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", media->length); + ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size); + ippDelete(media_size); + + if (source) + ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-source", NULL, _ppdCacheGetSource(p->pc, source)); + + if (type) + ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-type", NULL, _ppdCacheGetType(p->pc, type)); + + ippAddCollection(col, IPP_TAG_ZERO, "media-col", media_col); + ippDelete(media_col); + } + } + + cupsArrayDelete(preset); + + // Add the value + if (attr) + ippSetCollection(p->ppd_attrs, &attr, ippGetCount(attr), col); + else + attr = ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "job-presets-supported", col); + + ippDelete(col); + } + if (ppd->throughput) { ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -4171,16 +4296,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, p->make_model); -#if 0 // TODO: Save global strings - if (p->pc && p->pc->strings) - _cupsMessageSave(strings_name, _CUPS_MESSAGE_STRINGS, p->pc->strings); - - if (!access(strings_name, R_OK)) - cupsdSetString(&p->strings, strings_name); - else - cupsdClearString(&p->strings); -#endif // 0 - num_urf = 0; urf[num_urf ++] = "V1.4"; urf[num_urf ++] = "CP1";