cupsDestAddMediaOption and cupsDestMedia... APIs do not provide control over source or type
I'm trying to select a media-source for a HP LaserJet 1520 Series printer, but I am having a hard time understanding why it works by setting InputSlot cupsAddOption("InputSlot", ...) and not media-source cupsAddOption("media-source", ...). If I can "query" the printer trays using media-source but not InputSlot, then why would it not work to set the tray using media-source? Is this a bug or a known/undocumented process?
I'm on OSX Big Sur. Cups reported version is 2.3.4 (cups-config --version). I have also tried compiling against a build of master in this repo and it behaves the same.
I added two queues for the printer in OSX. One points to the printer using AirPrint, and the other points to the printer using a ppd file supplied by HP (installed via the HP Easy Start program).
The printer has 2 trays.. a manual feed tray and an auto feed.
The HP_LaserJet_CP1525nw (AirPrint) behavior is that it defaults to the auto-feed tray. I can only change the tray using the InputSlot option:
ippFindAttribute(ipp_response, "media-source-supported", IPP_TAG_ZERO); // Returns 2 sources, "main-tray" and "alternate-tray"
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", NULL); // returns true
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", "main-tray"); // returns true
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", "AlternateTray"); // returns false
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", "alternate-tray"); // returns true
// I've tried these options:
cupsAddOption("media-source", "alternate-tray", num_options, &options); // Still prints using Main Tray (WRONG)
cupsAddOption("media-source", "AlternateTray", num_options, &options); // Still prints using Main Tray (WRONG)
cupsAddOption("InputSlot", "Alternate Tray", num_options, &options); // Still prints using Main Tray (WRONG)
cupsAddOption("InputSlot", "AlternateTray", num_options, &options); // Prints using manual tray (CORRECT)
cupsAddOption("InputSlot", "alternate-tray", num_options, &options); // Prints using manual tray (CORRECT)
Here is a snippet of the ppd file for the AirPrint-based printer (in /private/etc/cups):
*% PPD created by ipp2ppd (v3:Dec 22 2020)
...
*OpenUI *InputSlot: PickOne
*OrderDependency: 10 AnySetup *InputSlot
*InputSlot main-tray: ""
*InputSlot alternate-tray: ""
*DefaultInputSlot: Unknown
The HP_LaserJet_CP1525nw (HP PPD) behavior is that it defaults to the manual feed tray. I can only change the tray using the InputSlot option:
ippFindAttribute(ipp_response, "media-source-supported", IPP_TAG_ZERO); // Returns 3 sources, "tray-1" and "tray-2", "tray-1-man"
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", NULL); // returns true
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", "tray-2"); // returns true
cupsCheckDestSupported(cupsConnection, printer, printer_info, "media-source", "tray-1"); // returns true
// I've tried these two options:
cupsAddOption("media-source", "tray-2", num_options, &options); // Still prints using manual tray (WRONG)
cupsAddOption("InputSlot", "Tray2", num_options, &options); // Prints using the auto tray (CORRECT)
Here is a snippet of the ppd file from HP (in /private/etc/cups):
*%%%% PPD file for HP LaserJet CP1520 Series with CUPS.
*%%%% Created by the CUPS PPD Compiler CUPS v1.5svn.
*% © Copyright 2009-2015 HP Development Company, L.P.
*% PPD Version for OS X
...
*DefaultInputSlot: Tray1
*InputSlot Tray1/Tray 1: "<</MediaPosition 3 /ManualFeed false>> setpagedevice"
*InputSlot Tray2/Tray 2: "<</MediaPosition 0 /ManualFeed false>> setpagedevice"
*InputSlot Tray1_Man/Tray 1 (Manual): "<</MediaPosition 3 /ManualFeed true>> setpagedevice"
*CloseUI: *InputSlot
@emusgrave "media-source" is a member attribute of "media-col" (the media collection). There is actually an API for adding this (cupsAddDestMediaOptions) that was added in CUPS 2.3, but if you need to support older CUPS releases use then format a "media-col" value like this:
"{media-size-name=SIZE media-source=SOURCE}"
@michaelrsweet I have confirmed that using cupsAddOption to set "media-col" with a valid "media-source" works:
num_options =
cupsAddOption("media-col",
"{media-size={x-dimension=21590 y-dimension=27940} media-bottom-margin=423 media-left-margin=423 media-right-margin=423 media-top-margin=423 media-source=\"alternate-tray\"}",
num_options,
&options);
However, I don't see how cupsAddDestMediaOptions would allow me to set a different media-source for this printer. I traced into the function and this is what I'm seeing:
First, the printer doesn't have any values for media-ready/media-col-ready, so the function doesn't do anything unless I first "force" the dinfo->media_db to be populated by calling one of the functions like cupsGetDestMediaCount. Otherwise, the dinfo has a null media_db and an empty (0 elements) ready_db when I call cupsAddDestMediaOptions. That function therefore doesn't find any matches to the size parameter.
Once I've forced the media_db to be generated, the issue is that the media-col-database for my printer does not populate the media-source. For example, the media-col-default for my printer is this (no name, source, type, or duplex-supported values):
media-col-default = {media-size={x-dimension=21590 y-dimension=27940} media-bottom-margin=423 media-left-margin=423 media-right-margin=423 media-top-margin=423}
So, using cupsAddDestMediaOptions to set the media does not actually set a media-source, and there's no way to pass a media-source into that function to force the value.
One other note is that if I connect to the printer directly using CUPS_DEST_FLAGS_DEVICE, then the media database does populate with media-source for each media. BUT, that doesn't really help out in using cupsAddDestMediaOptions because it will still just use the default media-source for each media size... there's no way for me to use that function to set a different source tray than what is already specified for that particular media. In my example when connecting directly to the device, all the media-source's are set to the main-tray, so there is no way for that function to let me change it to the alternate-tray.
In summary, I can make my code work by always using cupsAddOption with "media-col", but if that is considered the "old-way" to change media-source then I'd like to understand if I'm misusing cupsAddDestMediaOptions.
OK, so the fact that cupsAddDestMediaOptions isn't populating media_db is probably a bug - will look into that.
And as for the media source... OK looking at the code it is mapping media-key from media-col-database/ready to the name field in cups_size_t. Which works as long as there is a unique mapping to source and type (and not the typical "wildcard" that most printers return, at least for media-col-database...)
OK, for now use the "old" way with "media-col" and cupsAddOption, we'll need to come up with a better long-term solution for this.
Updated the title and assigned this to 2.4.0 so we can provide a proper API.
OK, so we have a new API using the cups_media_t structure instead of the old cups_size_t structure, to use with cupsAddMediaOptions2 and the related cupsGetMediaByXxx2 APIs.