]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | <!-- |
bc44d920 | 2 | "$Id: api-filter.shtml 6649 2007-07-11 21:46:42Z mike $" |
ef416fc2 | 3 | |
5a738aea MS |
4 | Filter and backend programming introduction for the Common UNIX Printing |
5 | System (CUPS). | |
ef416fc2 | 6 | |
5a738aea | 7 | Copyright 2007-2008 by Apple Inc. |
bc44d920 | 8 | Copyright 1997-2006 by Easy Software Products, all rights reserved. |
ef416fc2 | 9 | |
10 | These coded instructions, statements, and computer programs are the | |
bc44d920 | 11 | property of Apple Inc. and are protected by Federal copyright |
12 | law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
13 | which should have been included with this file. If this file is | |
14 | file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 15 | --> |
16 | ||
5a738aea | 17 | <h2 class='title'><a name="OVERVIEW">Overview</a></h2> |
ef416fc2 | 18 | |
5a738aea MS |
19 | <p>Filters, printer drivers, port monitors, and backends use a common interface |
20 | for processing print jobs and communicating status information to the scheduler. | |
21 | Each filter is run with a standard set of command-line arguments:<p> | |
ef416fc2 | 22 | |
5a738aea | 23 | <dl class="code"> |
ef416fc2 | 24 | |
5a738aea MS |
25 | <dt>argv[1]</dt> |
26 | <dd>The job ID</dd> | |
ef416fc2 | 27 | |
5a738aea MS |
28 | <dt>argv[2]</dt> |
29 | <dd>The user printing the job</dd> | |
f7deaa1a | 30 | |
5a738aea MS |
31 | <dt>argv[3]</dt> |
32 | <dd>The job name/title</dd> | |
ef416fc2 | 33 | |
5a738aea MS |
34 | <dt>argv[4]</dt> |
35 | <dd>The number of copies to print</dd> | |
ef416fc2 | 36 | |
5a738aea MS |
37 | <dt>argv[5]</dt> |
38 | <dd>The options that were provided when the job was submitted</dd> | |
f7deaa1a | 39 | |
5a738aea MS |
40 | <dt>argv[6]</dt> |
41 | <dd>The file to print (first filter only)</dd> | |
42 | </dl> | |
ef416fc2 | 43 | |
5a738aea MS |
44 | <p>The scheduler runs one or more of these programs to print any given job. The |
45 | first filter reads from the print file and writes to the standard output, while | |
46 | the remaining filters read from the standard input and write to the standard | |
47 | output. The backend is the last filter in the chain and writes to the | |
48 | device.</p> | |
f7deaa1a | 49 | |
5a738aea | 50 | <h3><a name="EXITCODES">Exit Codes</a></h3> |
f7deaa1a | 51 | |
5a738aea MS |
52 | <p>Filters must exit with status 0 when they successfully generate print data |
53 | or 1 when they encounter an error. Backends can return any of the | |
54 | <a href="#cups_backend_t"><code>cups_backend_t</code></a> constants.</p> | |
f7deaa1a | 55 | |
5a738aea | 56 | <h3><a name="ENVIRONMENT">Environment Variables</a></h3> |
f7deaa1a | 57 | |
5a738aea | 58 | <p>The following environment variables are defined by the printing system:</p> |
f7deaa1a | 59 | |
5a738aea | 60 | <dl class="code"> |
f7deaa1a | 61 | |
5a738aea MS |
62 | <dt>APPLE_LANGUAGES</dt> |
63 | <dd>The Apple language identifier associated with the job | |
64 | (Mac OS X only).</dd> | |
f7deaa1a | 65 | |
5a738aea MS |
66 | <dt>CHARSET</dt> |
67 | <dd>The job character set, typically "utf-8".</dd> | |
f7deaa1a | 68 | |
5a738aea MS |
69 | <dt>CLASS</dt> |
70 | <dd>When a job is submitted to a printer class, contains the name of | |
71 | the destination printer class. Otherwise this environment | |
72 | variable will not be set.</dd> | |
f7deaa1a | 73 | |
5a738aea MS |
74 | <dt>CONTENT_TYPE</dt> |
75 | <dd>The MIME type associated with the file (e.g. | |
76 | application/postscript).</dd> | |
f7deaa1a | 77 | |
5a738aea MS |
78 | <dt>CUPS_CACHEDIR</dt> |
79 | <dd>The directory where cache files can be stored.</dd> | |
f7deaa1a | 80 | |
5a738aea MS |
81 | <dt>CUPS_DATADIR</dt> |
82 | <dd>The directory where data files can be found.</dd> | |
f7deaa1a | 83 | |
5a738aea MS |
84 | <dt>CUPS_SERVERROOT</dt> |
85 | <dd>The root directory of the server.</dd> | |
f7deaa1a | 86 | |
5a738aea MS |
87 | <dt>DEVICE_URI</dt> |
88 | <dd>The device-uri associated with the printer.</dd> | |
f7deaa1a | 89 | |
5a738aea MS |
90 | <dt>FINAL_CONTENT_TYPE</dt> |
91 | <dd>The MIME type associated with the printer (e.g. | |
92 | application/vnd.cups-postscript).</dd> | |
f7deaa1a | 93 | |
5a738aea MS |
94 | <dt>LANG</dt> |
95 | <dd>The language locale associated with the job.</dd> | |
f7deaa1a | 96 | |
5a738aea MS |
97 | <dt>PPD</dt> |
98 | <dd>The full pathname of the PostScript Printer Description (PPD) | |
99 | file for this printer.</dd> | |
f7deaa1a | 100 | |
5a738aea MS |
101 | <dt>PRINTER</dt> |
102 | <dd>The name of the printer.</dd> | |
f7deaa1a | 103 | |
5a738aea MS |
104 | <dt>RIP_CACHE</dt> |
105 | <dd>The recommended amount of memory to use for Raster Image | |
106 | Processors (RIPs).</dd> | |
f7deaa1a | 107 | |
5a738aea | 108 | </dl> |
f7deaa1a | 109 | |
5a738aea | 110 | <h3><a name="MESSAGES">Communicating with the Scheduler</a></h3> |
f7deaa1a | 111 | |
5a738aea MS |
112 | <p>Filters and backends communicate wih the scheduler by writing messages |
113 | to the standard error file. For example, the following code sets the current | |
114 | printer state message to "Printing page 5":</p> | |
f7deaa1a | 115 | |
5a738aea MS |
116 | <pre class="example"> |
117 | int page = 5; | |
f7deaa1a | 118 | |
5a738aea MS |
119 | fprintf(stderr, "INFO: Printing page %d\n", page); |
120 | </pre> | |
f7deaa1a | 121 | |
5a738aea MS |
122 | <p>Each message is a single line of text starting with one of the following |
123 | prefix strings:</p> | |
124 | ||
125 | <dl class="code"> | |
126 | ||
127 | <dt>ALERT: message</dt> | |
128 | <dd>Sets the printer-state-message attribute and adds the specified | |
129 | message to the current error log file using the "alert" log level.</dd> | |
130 | ||
131 | <dt>ATTR: attribute=value [attribute=value]</dt> | |
132 | <dd>Sets the named printer or job attribute(s). Typically this is used | |
133 | to set the <code>marker-colors</code>, <code>marker-levels</code>, | |
134 | <code>marker-names</code>, <code>marker-types</code>, | |
135 | <code>printer-alert</code>, and <code>printer-alert-description</code> | |
136 | printer attributes.</dd> | |
137 | ||
138 | <dt>CRIT: message</dt> | |
139 | <dd>Sets the printer-state-message attribute and adds the specified | |
140 | message to the current error log file using the "critical" log | |
141 | level.</dd> | |
142 | ||
143 | <dt>DEBUG: message</dt> | |
144 | <dd>Sets the printer-state-message attribute and adds the specified | |
145 | message to the current error log file using the "debug" log level.</dd> | |
146 | ||
147 | <dt>DEBUG2: message</dt> | |
148 | <dd>Sets the printer-state-message attribute and adds the specified | |
149 | message to the current error log file using the "debug2" log level.</dd> | |
150 | ||
151 | <dt>EMERG: message</dt> | |
152 | <dd>Sets the printer-state-message attribute and adds the specified | |
153 | message to the current error log file using the "emergency" log | |
154 | level.</dd> | |
155 | ||
156 | <dt>ERROR: message</dt> | |
157 | <dd>Sets the printer-state-message attribute and adds the specified | |
158 | message to the current error log file using the "error" log level.</dd> | |
159 | ||
160 | <dt>INFO: message</dt> | |
161 | <dd>Sets the printer-state-message attribute. If the current log level | |
162 | is set to "debug2", also adds the specified message to the current error | |
163 | log file using the "info" log level.</dd> | |
164 | ||
165 | <dt>NOTICE: message</dt> | |
166 | <dd>Sets the printer-state-message attribute and adds the specified | |
167 | message to the current error log file using the "notice" log level.</dd> | |
168 | ||
169 | <dt>PAGE: page-number #-copies</dt> | |
170 | <dt>PAGE: total #-pages</dt> | |
171 | <dd>Adds an entry to the current page log file. The first form adds | |
172 | #-copies to the job-media-sheets-completed attribute. The second | |
173 | form sets the job-media-sheets-completed attribute to #-pages.</dd> | |
174 | ||
175 | <dt>STATE: printer-state-reason [printer-state-reason ...]</dt> | |
176 | <dt>STATE: + printer-state-reason [printer-state-reason ...]</dt> | |
177 | <dt>STATE: - printer-state-reason [printer-state-reason ...]</dt> | |
178 | <dd>Sets, adds, or removes printer-state-reason keywords to the | |
179 | current queue. Typically this is used to indicate media, ink, and | |
180 | toner conditions on a printer.</dd> | |
181 | ||
182 | <dt>WARNING: message</dt> | |
183 | <dd>Sets the printer-state-message attribute and adds the specified | |
184 | message to the current error log file using the "warning" log | |
185 | level.</dd> | |
186 | ||
187 | </dl> | |
188 | ||
189 | <p>Messages without one of these prefixes are treated as if they began with | |
190 | the "DEBUG:" prefix string.</p> | |
191 | ||
192 | <h3><a name="COMMUNICATING">Communicating with the Backend</a></h3> | |
193 | ||
194 | <p>Filters can communicate with the backend via the | |
195 | <a href="#cupsBackChannelRead"><code>cupsBackChannelRead</code></a> and | |
196 | <a href="#cupsSideChannelDoRequest"><code>cupsSideChannelDoRequest</code></a> | |
197 | functions. The | |
198 | <a href="#cupsBackChannelRead"><code>cupsBackChannelRead</code></a> function | |
199 | reads data that has been sent back from the device and is typically used to | |
200 | obtain status and configuration information. For example, the following code | |
201 | polls the backend for back-channel data:</p> | |
202 | ||
203 | <pre class="example"> | |
204 | #include <cups/cups.h> | |
f7deaa1a | 205 | |
5a738aea MS |
206 | char buffer[8192]; |
207 | ssize_t bytes; | |
f7deaa1a | 208 | |
5a738aea MS |
209 | /* Use a timeout of 0.0 seconds to poll for back-channel data */ |
210 | bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0.0); | |
f7deaa1a | 211 | </pre> |
212 | ||
5a738aea MS |
213 | The |
214 | <a href="#cupsSideChannelDoRequest"><code>cupsSideChannelDoRequest</code></a> | |
215 | function allows you to get out-of-band status information and do synchronization | |
216 | with the device. For example, the following code gets the current IEEE-1284 | |
217 | device ID string from the backend:</p> | |
f7deaa1a | 218 | |
5a738aea | 219 | <pre class="example"> |
f7deaa1a | 220 | #include <cups/sidechannel.h> |
221 | ||
222 | char data[2049]; | |
223 | int datalen; | |
5a738aea | 224 | <a href="#cups_sc_status_t">cups_sc_status_t</a> status; |
f7deaa1a | 225 | |
226 | /* Tell cupsSideChannelDoRequest() how big our buffer is, less 1 byte for nul-termination... */ | |
227 | datalen = sizeof(data) - 1; | |
228 | ||
229 | /* Get the IEEE-1284 device ID, waiting for up to 1 second */ | |
5a738aea | 230 | status = <a href="#cupsSideChannelDoRequest">cupsSideChannelDoRequest</a>(CUPS_SC_CMD_GET_DEVICE_ID, data, &datalen, 1.0); |
f7deaa1a | 231 | |
232 | /* Use the returned value if OK was returned and the length is non-zero */ | |
233 | if (status == CUPS_SC_STATUS_OK && datalen > 0) | |
234 | data[datalen] = '\0'; | |
235 | else | |
236 | data[0] = '\0'; | |
237 | </pre> | |
238 | ||
5a738aea MS |
239 | <p>Backends communicate with filters using the reciprocal functions |
240 | <a href="#cupsBackChannelWrite"><code>cupsBackChannelWrite</code></a>, | |
241 | <a href="#cupsSideChannelRead"><code>cupsSideChannelRead</code></a>, and | |
242 | <a href="#cupsSideChannelWrite"><code>cupsSideChannelWrite</code></a>. We | |
243 | recommend writing back-channel data using a timeout of 1.0 seconds:</p> | |
f7deaa1a | 244 | |
5a738aea MS |
245 | <pre class="example"> |
246 | #include <cups/cups.h> | |
f7deaa1a | 247 | |
5a738aea MS |
248 | char buffer[8192]; |
249 | ssize_t bytes; | |
f7deaa1a | 250 | |
5a738aea MS |
251 | /* Use a timeout of 1.0 seconds to give filters a chance to read */ |
252 | cupsBackChannelWrite(buffer, bytes, 1.0); | |
f7deaa1a | 253 | </pre> |
254 | ||
5a738aea MS |
255 | <p>The <a href="#cupsSideChannelRead"><code>cupsSideChannelRead</code></a> |
256 | function reads a side-channel command from a filter, driver, or port monitor. | |
257 | Backends can either poll for commands using a <code>timeout</code> of 0.0, wait | |
258 | indefinitely for commands using a <code>timeout</code> of -1.0 (probably in a | |
259 | separate thread for that purpose), or use <code>select</code> or | |
260 | <code>poll</code> on the <code>CUPS_SC_FD</code> file descriptor (4) to handle | |
261 | input and output on several file descriptors at the same time. Backends can pass | |
262 | <code>NULL</code> for the <code>data</code> and <code>datalen</code> parameters | |
263 | since none of the commands sent by upstream filters contain any data at this | |
264 | time.</p> | |
265 | ||
266 | <p>Once a command is processed, the backend uses the | |
267 | <a href="#cupsSideChannelWrite"><code>cupsSideChannelWrite</code></a> function | |
268 | to send its response. For example, the following code shows how to poll for a | |
269 | side-channel command and respond to it:</p> | |
270 | ||
271 | <pre class="example"> | |
f7deaa1a | 272 | #include <cups/sidechannel.h> |
273 | ||
5a738aea MS |
274 | <a href="#cups_sc_command_t">cups_sc_command_t</a> command; |
275 | <a href="#cups_sc_status_t">cups_sc_status_t</a> status; | |
f7deaa1a | 276 | |
277 | /* Poll for a command... */ | |
5a738aea | 278 | if (!<a href="#cupsSideChannelRead">cupsSideChannelRead</a>(&command, &status, NULL, NULL, 0.0)) |
f7deaa1a | 279 | { |
280 | char data[2048]; | |
281 | int datalen; | |
282 | ||
283 | switch (command) | |
284 | { | |
5a738aea | 285 | /* handle supported commands, file data/datalen/status with values as needed */ |
f7deaa1a | 286 | |
287 | default : | |
288 | status = CUPS_SC_STATUS_NOT_IMPLEMENTED; | |
289 | datalen = 0; | |
290 | break; | |
291 | } | |
292 | ||
293 | /* Send a response... */ | |
5a738aea | 294 | <a href="#cupsSideChannelWrite">cupsSideChannelWrite</a>(command, status, data, datalen, 1.0); |
f7deaa1a | 295 | } |
296 | </pre> |