]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/api-filter.shtml
Merge changes from CUPS 1.4svn-r7282.
[thirdparty/cups.git] / cups / api-filter.shtml
index 0eda305c7a01d5297b2ecc20cb96a6ed27ad9947..4f72dfe7193fc9632f969f7d587b8fcdf25db776 100644 (file)
@@ -1,9 +1,10 @@
 <!--
   "$Id: api-filter.shtml 6649 2007-07-11 21:46:42Z mike $"
 
-  Filter and backend API introduction for the Common UNIX Printing System (CUPS).
+  Filter and backend programming introduction for the Common UNIX Printing
+  System (CUPS).
 
-  Copyright 2007 by Apple Inc.
+  Copyright 2007-2008 by Apple Inc.
   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 
   These coded instructions, statements, and computer programs are the
   file is missing or damaged, see the license at "http://www.cups.org/".
 -->
 
-<h2 class='title'>Introduction</h2>
+<h2 class='title'><a name="OVERVIEW">Overview</a></h2>
 
-<p>The CUPS filter and backend APIs define standard exit codes
-and provide access to the backchannel data stream. They are only
-used when writing backends, filters, and port monitors.</p>
+<p>Filters, printer drivers, port monitors, and backends use a common interface
+for processing print jobs and communicating status information to the scheduler.
+Each filter is run with a standard set of command-line arguments:<p>
 
-<h2 class='title'>General Usage</h2>
+<dl class="code">
 
-<p>The <var>&lt;cups/backend.h&gt;</var> and
-<var>&lt;cups/cups.h&gt;</var> header files must be included to
-use the <tt>CUPS_BACKEND_</tt> constants and
-<tt>cupsBackChannel</tt> functions, respectively.</p>
+       <dt>argv[1]</dt>
+       <dd>The job ID</dd>
 
-<p>The <var>&lt;cups/sidechannel.h&gt;</var> header file must be
-included to use the <tt>CUPS_SC_</tt> constants and <tt>cupsSideChannel</tt> functions.</p>
+       <dt>argv[2]</dt>
+       <dd>The user printing the job</dd>
 
-<p>Programs using these functions must be linked to the CUPS
-library: <var>libcups.a</var>, <var>libcups.so.2</var>,
-<var>libcups.2.dylib</var>, <var>libcups_s.a</var>, or
-<var>libcups2.lib</var> depending on the platform. The following
-command compiles <var>myprogram.c</var> using GCC and the CUPS
-library:</p>
+       <dt>argv[3]</dt>
+       <dd>The job name/title</dd>
 
-<pre class='command'>
-<kbd>gcc -o myprogram myprogram.c -lcups</kbd>
-</pre>
+       <dt>argv[4]</dt>
+       <dd>The number of copies to print</dd>
 
+       <dt>argv[5]</dt>
+       <dd>The options that were provided when the job was submitted</dd>
 
-<h2 class='title'>Compatibility</h2>
+       <dt>argv[6]</dt>
+       <dd>The file to print (first filter only)</dd>
+</dl>
 
-<p>The <tt>cupsBackChannel</tt> functions require CUPS 1.2 or higher. The <tt>cupsSideChannel</tt> functions require CUPS 1.3 or higher.</p>
+<p>The scheduler runs one or more of these programs to print any given job. The
+first filter reads from the print file and writes to the standard output, while
+the remaining filters read from the standard input and write to the standard
+output. The backend is the last filter in the chain and writes to the
+device.</p>
 
+<h3><a name="EXITCODES">Exit Codes</a></h3>
 
-<h2 class='title'>Using the cupsBackChannel APIs</h2>
+<p>Filters must exit with status 0 when they successfully generate print data
+or 1 when they encounter an error. Backends can return any of the
+<a href="#cups_backend_t"><code>cups_backend_t</code></a> constants.</p>
 
-<p>The <tt>cupsBackChannel</tt> APIs allow your filters, drivers, and port monitors to read data back from a printer and your backends to send data from a printer to the filters, drivers, and port monitors associated with the current job. Back-channel data is normally sent by the printer in response to a command sent from your program to the printer via <tt>stdout</tt>.</p>
+<h3><a name="ENVIRONMENT">Environment Variables</a></h3>
 
-<p>The <tt>cupsBackChannelRead()</tt> function reads data from the printer via the backend. You provide a timeout in seconds along with a buffer pointer and the size of that buffer. It returns the number of bytes or -1 if there was an error. The following code example shows how to poll for back-channel data in your program:</p>
+<p>The following environment variables are defined by the printing system:</p>
 
-<pre class='command'>
-#include &lt;cups/cups.h&gt;
+<dl class="code">
 
-char buffer[8192];
-ssize_t bytes;
+       <dt>APPLE_LANGUAGES</dt>
+       <dd>The Apple language identifier associated with the job
+       (Mac OS X only).</dd>
 
-/* Use a timeout of 0.0 seconds to poll for back-channel data */
-bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0.0);
-</pre>
+       <dt>CHARSET</dt>
+       <dd>The job character set, typically "utf-8".</dd>
 
-<p>If you are writing a backend, the <tt>cupsBackChannelWrite()</tt> function sends any back-channel data you have received from the printer to upstream filters in the print filter chain. We recommend using a timeout of 1.0 seconds:</p>
+       <dt>CLASS</dt>
+       <dd>When a job is submitted to a printer class, contains the name of
+       the destination printer class. Otherwise this environment
+       variable will not be set.</dd>
 
-<pre class='command'>
-#include &lt;cups/cups.h&gt;
+       <dt>CONTENT_TYPE</dt>
+       <dd>The MIME type associated with the file (e.g.
+       application/postscript).</dd>
 
-char buffer[8192];
-ssize_t bytes;
-
-/* Use a timeout of 1.0 seconds to give filters a chance to read */
-cupsBackChannelWrite(buffer, bytes, 1.0);
-</pre>
+       <dt>CUPS_CACHEDIR</dt>
+       <dd>The directory where cache files can be stored.</dd>
 
+       <dt>CUPS_DATADIR</dt>
+       <dd>The directory where data files can be found.</dd>
 
-<h2 class='title'>Using the cupsSideChannel APIs</h2>
+       <dt>CUPS_SERVERROOT</dt>
+       <dd>The root directory of the server.</dd>
 
-<p>The <tt>cupsSideChannel</tt> APIs allow your filters, drivers, port monitors, and backend to send and receive the following out-of-band commands:</p>
+       <dt>DEVICE_URI</dt>
+       <dd>The device-uri associated with the printer.</dd>
 
-<ul>
+       <dt>FINAL_CONTENT_TYPE</dt>
+       <dd>The MIME type associated with the printer (e.g.
+       application/vnd.cups-postscript).</dd>
 
-       <li><tt>CUPS_SC_CMD_SOFT_RESET</tt> -  Do a soft reset</li>
-       <li><tt>CUPS_SC_CMD_DRAIN_OUTPUT</tt> -  Drain all pending output</li>
-       <li><tt>CUPS_SC_CMD_GET_BIDI</tt> -  Return bidirectional capabilities</li>
-       <li><tt>CUPS_SC_CMD_GET_DEVICE_ID</tt> -  Return the IEEE-1284 device ID</li>
-       <li><tt>CUPS_SC_CMD_GET_STATE</tt> - Return the device state</li>
+       <dt>LANG</dt>
+       <dd>The language locale associated with the job.</dd>
 
-</ul>
+       <dt>PPD</dt>
+       <dd>The full pathname of the PostScript Printer Description (PPD)
+       file for this printer.</dd>
 
+       <dt>PRINTER</dt>
+       <dd>The name of the printer.</dd>
 
-<h3>Sending Commands from a Filter, Driver, or Port Monitor</h3>
+       <dt>RIP_CACHE</dt>
+       <dd>The recommended amount of memory to use for Raster Image
+       Processors (RIPs).</dd>
 
-<p>The <tt>cupsSideChannelDoRequest()</tt> function is used by filters, drivers, and port monitors to send a command to the backend and read back a response:</p>
-
-<pre class='command'>
-cups_sc_status_t cupsSideChannelDoRequest(cups_sc_command_t command,
-                                          char *data, int *datalen,
-                                          double timeout);
-</pre>
+</dl>
 
-<p>The <tt>CUPS_SC_CMD_SOFT_RESET</tt> and <tt>CUPS_SC_CMD_DRAIN_OUTPUT</tt> commands do not return any data values, while the others return one or more bytes. The <tt>timeout</tt> parameter allows your program to poll or wait for the command to complete - use a timeout of 30 seconds for <tt>CUPS_SC_CMD_SOFT_RESET</tt> and <tt>CUPS_SC_CMD_DRAIN_OUTPUT</tt> and a timeout of 1 second for all other commands.</p>
+<h3><a name="MESSAGES">Communicating with the Scheduler</a></h3>
 
-<p><tt>CUPS_SC_CMD_GET_BIDI</tt> returns a single <tt>char</tt> value that tells you whether the backend supports bidirectional communications:</p>
+<p>Filters and backends communicate wih the scheduler by writing messages
+to the standard error file. For example, the following code sets the current
+printer state message to "Printing page 5":</p>
 
-<pre class='command'>
-#include &lt;cups/sidechannel.h&gt;
+<pre class="example">
+int page = 5;
 
-char data;
-int datalen;
-cups_sc_bidi_t bidi;
-cups_sc_status_t status;
+fprintf(stderr, "INFO: Printing page %d\n", page);
+</pre>
 
-/* Tell cupsSideChannelDoRequest() how big our buffer is... */
-datalen = 1;
+<p>Each message is a single line of text starting with one of the following
+prefix strings:</p>
+
+<dl class="code">
+
+       <dt>ALERT: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "alert" log level.</dd>
+
+       <dt>ATTR: attribute=value [attribute=value]</dt>
+       <dd>Sets the named printer or job attribute(s). Typically this is used
+       to set the <code>marker-colors</code>, <code>marker-levels</code>,
+       <code>marker-names</code>, <code>marker-types</code>,
+       <code>printer-alert</code>, and <code>printer-alert-description</code>
+       printer attributes.</dd>
+
+       <dt>CRIT: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "critical" log
+       level.</dd>
+
+       <dt>DEBUG: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "debug" log level.</dd>
+
+       <dt>DEBUG2: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "debug2" log level.</dd>
+
+       <dt>EMERG: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "emergency" log
+       level.</dd>
+
+       <dt>ERROR: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "error" log level.</dd>
+
+       <dt>INFO: message</dt>
+       <dd>Sets the printer-state-message attribute. If the current log level
+       is set to "debug2", also adds the specified message to the current error
+       log file using the "info" log level.</dd>
+
+       <dt>NOTICE: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "notice" log level.</dd>
+
+       <dt>PAGE: page-number #-copies</dt>
+       <dt>PAGE: total #-pages</dt>
+       <dd>Adds an entry to the current page log file. The first form adds
+       #-copies to the job-media-sheets-completed attribute. The second
+       form sets the job-media-sheets-completed attribute to #-pages.</dd>
+
+       <dt>STATE: printer-state-reason [printer-state-reason ...]</dt>
+       <dt>STATE: + printer-state-reason [printer-state-reason ...]</dt>
+       <dt>STATE: - printer-state-reason [printer-state-reason ...]</dt>
+       <dd>Sets, adds, or removes printer-state-reason keywords to the
+       current queue. Typically this is used to indicate media, ink, and
+       toner conditions on a printer.</dd>
+
+       <dt>WARNING: message</dt>
+       <dd>Sets the printer-state-message attribute and adds the specified
+       message to the current error log file using the "warning" log
+       level.</dd>
+
+</dl>
+
+<p>Messages without one of these prefixes are treated as if they began with
+the "DEBUG:" prefix string.</p>
+
+<h3><a name="COMMUNICATING">Communicating with the Backend</a></h3>
+
+<p>Filters can communicate with the backend via the
+<a href="#cupsBackChannelRead"><code>cupsBackChannelRead</code></a> and
+<a href="#cupsSideChannelDoRequest"><code>cupsSideChannelDoRequest</code></a>
+functions. The 
+<a href="#cupsBackChannelRead"><code>cupsBackChannelRead</code></a> function
+reads data that has been sent back from the device and is typically used to
+obtain status and configuration information. For example, the following code
+polls the backend for back-channel data:</p>
+
+<pre class="example">
+#include &lt;cups/cups.h&gt;
 
-/* Get the bidirectional capabilities, waiting for up to 1 second */
-status  = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, &amp;data, &amp;datalen, 1.0);
+char buffer[8192];
+ssize_t bytes;
 
-/* Use the returned value if OK was returned and the length is still 1 */
-if (status == CUPS_SC_STATUS_OK && datalen == 1)
-  bidi = (cups_sc_bidi_t)data;
-else
-  bidi = CUPS_SC_BIDI_NOT_SUPPORTED;
+/* Use a timeout of 0.0 seconds to poll for back-channel data */
+bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0.0);
 </pre>
 
-<p><tt>CUPS_SC_CMD_GET_DEVICE_ID</tt> returns a string of characters containing the IEEE-1284 device ID for the connected printer:</p>
+The
+<a href="#cupsSideChannelDoRequest"><code>cupsSideChannelDoRequest</code></a>
+function allows you to get out-of-band status information and do synchronization
+with the device. For example, the following code gets the current IEEE-1284
+device ID string from the backend:</p>
 
-<pre class='command'>
+<pre class="example">
 #include &lt;cups/sidechannel.h&gt;
 
 char data[2049];
 int datalen;
-cups_sc_status_t status;
+<a href="#cups_sc_status_t">cups_sc_status_t</a> status;
 
 /* Tell cupsSideChannelDoRequest() how big our buffer is, less 1 byte for nul-termination... */
 datalen = sizeof(data) - 1;
 
 /* Get the IEEE-1284 device ID, waiting for up to 1 second */
-status  = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_DEVICE_ID, data, &amp;datalen, 1.0);
+status = <a href="#cupsSideChannelDoRequest">cupsSideChannelDoRequest</a>(CUPS_SC_CMD_GET_DEVICE_ID, data, &amp;datalen, 1.0);
 
 /* Use the returned value if OK was returned and the length is non-zero */
 if (status == CUPS_SC_STATUS_OK && datalen > 0)
@@ -147,59 +236,53 @@ else
   data[0] = '\0';
 </pre>
 
-<p><tt>CUPS_SC_CMD_GET_STATE</tt> returns a single <tt>char</tt> value that tells you the current device state:</p>
-
-<pre class='command'>
-#include &lt;cups/sidechannel.h&gt;
+<p>Backends communicate with filters using the reciprocal functions
+<a href="#cupsBackChannelWrite"><code>cupsBackChannelWrite</code></a>,
+<a href="#cupsSideChannelRead"><code>cupsSideChannelRead</code></a>, and
+<a href="#cupsSideChannelWrite"><code>cupsSideChannelWrite</code></a>. We
+recommend writing back-channel data using a timeout of 1.0 seconds:</p>
 
-char data;
-int datalen;
-cups_sc_state_t state;
-cups_sc_status_t status;
-
-/* Tell cupsSideChannelDoRequest() how big our buffer is... */
-datalen = 1;
-
-/* Get the bidirectional capabilities, waiting for up to 1 second */
-status  = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_STATE, &amp;data, &amp;datalen, 1.0);
-
-/* Use the returned value if OK was returned and the length is still 1 */
-if (status == CUPS_SC_STATUS_OK && datalen == 1)
-  state = (cups_sc_state_t)data;
-else
-  state = CUPS_SC_STATE_OFFLINE;
-</pre>
-
-
-<h3>Handling Commands in your Backend</h3>
+<pre class="example">
+#include &lt;cups/cups.h&gt;
 
-<p>The <tt>cupsSideChannelRead()</tt> function is used by backends to read a command from a filter, driver, or port monitor:</p>
+char buffer[8192];
+ssize_t bytes;
 
-<pre class='command'>
-int cupsSideChannelRead(cups_sc_command_t &amp;command,
-                        cups_sc_status_t  &amp;status,
-                        char *data, int *datalen, double timeout);
+/* Use a timeout of 1.0 seconds to give filters a chance to read */
+cupsBackChannelWrite(buffer, bytes, 1.0);
 </pre>
 
-<p>Backends can either poll for commands using a <tt>timeout</tt> of 0.0, wait indefinitely for commands using a <tt>timeout</tt> of -1.0 (probably in a separate thread for that purpose), or use <tt>select()</tt> or <tt>poll()</tt> on the <tt>CUPS_SC_FD</tt> file descriptor (4) to handle input and output on several file descriptors at the same time. Backends can pass <tt>NULL</tt> for the <tt>data</tt> and <tt>datalen</tt> parameters, since none of the commands sent by upstream filters contain any data at this time.</p>
-
-<p>Once a command is processed, the backend uses the <tt>cupsSideChannelWrite()</tt> function to send its response:</p>
-
-<pre class='command'>
+<p>The <a href="#cupsSideChannelRead"><code>cupsSideChannelRead</code></a>
+function reads a side-channel command from a filter, driver, or port monitor.
+Backends can either poll for commands using a <code>timeout</code> of 0.0, wait
+indefinitely for commands using a <code>timeout</code> of -1.0 (probably in a
+separate thread for that purpose), or use <code>select</code> or
+<code>poll</code> on the <code>CUPS_SC_FD</code> file descriptor (4) to handle
+input and output on several file descriptors at the same time. Backends can pass
+<code>NULL</code> for the <code>data</code> and <code>datalen</code> parameters
+since none of the commands sent by upstream filters contain any data at this
+time.</p>
+
+<p>Once a command is processed, the backend uses the
+<a href="#cupsSideChannelWrite"><code>cupsSideChannelWrite</code></a> function
+to send its response. For example, the following code shows how to poll for a
+side-channel command and respond to it:</p>
+
+<pre class="example">
 #include &lt;cups/sidechannel.h&gt;
 
-cups_sc_command_t command;
-cups_sc_status_t status;
+<a href="#cups_sc_command_t">cups_sc_command_t</a> command;
+<a href="#cups_sc_status_t">cups_sc_status_t</a> status;
 
 /* Poll for a command... */
-if (!cupsSideChannelRead(&amp;command, &amp;status, NULL, NULL, 0.0))
+if (!<a href="#cupsSideChannelRead">cupsSideChannelRead</a>(&amp;command, &amp;status, NULL, NULL, 0.0))
 {
   char data[2048];
   int datalen;
 
   switch (command)
   {
-    ... handle supported commands, file data/datalen/status with values as needed ...
+    /* handle supported commands, file data/datalen/status with values as needed */
 
     default :
         status  = CUPS_SC_STATUS_NOT_IMPLEMENTED;
@@ -208,6 +291,6 @@ if (!cupsSideChannelRead(&amp;command, &amp;status, NULL, NULL, 0.0))
   }
 
   /* Send a response... */
-  cupsSideChannelWrite(command, status, data, datalen, 1.0);
+  <a href="#cupsSideChannelWrite">cupsSideChannelWrite</a>(command, status, data, datalen, 1.0);
 }
 </pre>