Implementation of the %config%
(configuration) device type.
More...
#include "skinkit.h"
#include "kit.h"
#include "ripthread.h"
#include "kitdevs.h"
#include "swdevice.h"
#include "skintimeline.h"
#include "skindevs.h"
#include "hqmemcpy.h"
#include "swcopyf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
Enumerations | |
enum | { CONFIG_FIRST , CONFIG_START , CONFIG_DATA , CONFIG_END } |
Used to maintain the state of the device between read calls. More... | |
Functions | |
static void | config_set_last_error (DEVICE_result error) |
The stub functions for the configuration device to provide appropriate return codes for slots which have nothing else to do. | |
static DEVICE_FILEDESCRIPTOR | config_open_file (DEVICELIST *dev, uint8 *filename, int32 openflags) |
The open file routine for the config device type. See DEVICELIST_OPEN(). More... | |
static int32 | config_read_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, uint8 *buff, int32 len) |
The read_file routine for the config device type. See DEVICELIST_READ(). More... | |
static int32 | config_write_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, uint8 *buff, int32 len) |
Stub with correct protopype function pointer. See DEVICELIST_WRITE(). | |
static int32 | config_close_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor) |
The close_file routine for the config device type. See DEVICELIST_CLOSE(). | |
static int32 | config_seek_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, Hq32x2 *destination, int32 flags) |
The seek_file routine for the config device type. See DEVICELIST_SEEK(). | |
static int32 | config_bytes_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, Hq32x2 *bytes, int32 reason) |
The bytes_file routine for the config device type, the manifestation in C of the bytesavailable PostScript operator. See DEVICELIST_BYTES(). More... | |
static int32 | config_status_file (DEVICELIST *dev, uint8 *filename, STAT *statbuff) |
Call to check status of file. See DEVICELIST_STATUS_FILE(). | |
static void * | config_start_file_list (DEVICELIST *dev, uint8 *pattern) |
Call to start listing files. See DEVICELIST_START_LIST(). | |
static int32 | config_buffsize (DEVICELIST *dev) |
The buffsize routine for the config device type. Not required, but provided for example purposes. The 'len' parameter of the config_read_file() function will never exceed the amount we indicate with this function. See DEVICELIST_BUFFER_SIZE(). | |
static int32 | config_next_file (DEVICELIST *dev, void **handle, uint8 *pattern, FILEENTRY *entry) |
Call to get next file in list. See DEVICELIST_NEXT(). | |
static int32 | config_end_file_list (DEVICELIST *dev, void *handle) |
Call to end listing. See DEVICELIST_END_LIST(). | |
static int32 | config_rename_file (DEVICELIST *dev, uint8 *file1, uint8 *file2) |
Rename file on the device. See DEVICELIST_RENAME(). | |
static int32 | config_delete_file (DEVICELIST *dev, uint8 *filename) |
Remove file from device. See DEVICELIST_DELETE(). | |
static int32 | config_set_param (DEVICELIST *dev, DEVICEPARAM *param) |
Call to set device parameter. See DEVICELIST_SET_PARAM(). | |
static int32 | config_start_param (DEVICELIST *dev) |
Call to start getting device parameters. See DEVICELIST_START_PARAM(). | |
static int32 | config_get_param (DEVICELIST *dev, DEVICEPARAM *param) |
Call to start getting device parameters. See DEVICELIST_GET_PARAM(). | |
static int32 | config_status_device (DEVICELIST *dev, DEVSTAT *devstat) |
Call to get the status of the device. DEVICELIST_STATUS_DEVICE(). | |
static int32 | config_spare (void) |
Spare slot. See DEVICELIST_SPARE(). | |
Variables | |
static DEVICE_FILEDESCRIPTOR | config_fd = 0 |
static sw_tl_ref | skin_job = SW_TL_REF_INVALID |
static enum { ... } | config_status = CONFIG_FIRST |
Used to maintain the state of the device between read calls. More... | |
DEVICETYPE | Config_Device_Type |
The config device type structure. | |
Implementation of the %config%
(configuration) device type.
This is a minimal implementation of the config device type. It provides all the required functions, but only limited functionality.
The purpose of the configuration device type is twofold:
The discussion of the %config% device below is relevant when directly injecting PostScript jobs, and for OEMs who want to extend the input capabilities of the RIP. It is normally not necessary to directly inject PostScript jobs. Global Graphics recommends using the Input queue and source API with the SwLeProcessInputQueue() function to queue and process jobs. That function will set up the first buffer of PostScript returned to the %config% device in such a way that the RIP will detect the type of the job, perform appropriate configuration at the correct save levels, and read the job file directly. The method used to do this uses the /HqnConfigProvider
ProcSet to perform the configuration, and the HqnInputTypes
ProcSet to perform the input detection.
The RIP simply runs the configuration file. Therefore the read function of the configuration device provides PostScript fragments which the RIP executes. Like a PostScript procedure, this PostScript is expected to manipulate the operand stack. In particular it consumes no operands, and leaves a boolean object on top of the stack. If the boolean is true, two further items are expected on the stack: a pair of file objects, the first of which is a file open for reading which is the PostScript job to be executed, and second is a file opened for writing, to which anything written to PostScript's %stdout%
pseudo-device will be directed. If the boolean is false, the system will re-run the config device again.
Therefore the read call for the config device could just return in the supplied buffer the characters
(%console%)(r) file (%console%)(w) file true
on the first call; and no characters on the second call (indicating end-of-file to the RIP) - and the RIP would then act on the PostScript shown as described above, causing it to read PostScript from a file opened on a device called %console%. %console% must have been mounted and had its device type set in order for this to succeed. Normally this would be done in the file %os%Sys/ExtraDevices, but could be done anywhere - for example it could be included in the PostScript emitted by the %config% device.
Normally, however, the PostScript emitted by %config% will be somewhat more complex. The device may require to choose its input from among several possible input sources; and it will certainly want to set up some default environment in which the job may run. Even if the PostScript emitted is quite simple, the implementation of the %config% device may be quite complex - involving perhaps manipulating user interface dialogs which allow the user to select the job to be run.
A useful technique appropriate in some circumstances is to implement the function of the config device wholly in PostScript in which case the PostScript emitted by the config% device would simply be
(%os%my-config-file) run
and the PostScript file my-config-file on the %os% device would then be responsible for putting the two files and true onto the operand stack.
However, in our example below, we obtain this configuration PostScript by calling KGetConfigData(), repeatedly if necessary. This returns the PostScript provided to SwLeJobStart().
Finally, in order for the RIP to run %config%, the device must exist. It should be created (that is, mounted, enabled and assigned a device type number) in the Sys/ExtraDevices file, using PostScript similar to this:
statusdict begin (%config%) dup devmount pop << /Password 0 /DeviceType 16#ffff0002 /Enable true >> setdevparams end
(See kitdevs.h for a discussion of how 16#ffff0002 arises as the device type number).
This config device implementation accepts no device parameters. It is a non-relative device, so therefore many routines can be provided as stubs only. Furthermore, it will not be written to by the RIP as supplied so that functionality need not be supported. (However, you might consider implementing a write call on %config% for your own use, in place of a separate device type to receive PostScript messages written to standard error or standard output - see the discussion alongside the definition of the %console% device in monitor.c).
Note however that config_bytes_file() (bytesavailable in PostScript) MUST be implemented for the config device in order that the RIP can determine whether or not to run the %config% file.
This example also illustrates the use of the buffer size function, config_buffsize(). This is not a requirement, but since only a very small buffer is required in this example, we choose not to allow the RIP to waste space on a larger buffer as it would if this routine were not implemented.
anonymous enum |
Used to maintain the state of the device between read calls.
For a more comprehensive implementation this would be considerably more complex since more than one buffer full of information may have to be returned by the read file function.
Enumerator | |
---|---|
CONFIG_FIRST | No jobs have been run yet. |
CONFIG_START | Starting a new job on next read. |
CONFIG_DATA | Acquiring configuration data for job. |
CONFIG_END | Completed configuration data for job. |
|
static |
The bytes_file routine for the config device type, the manifestation in C of the bytesavailable PostScript operator. See DEVICELIST_BYTES().
This routine has special significance for the config device. This implementation simply returns the length of the PostScript string we would supply. If the amount of data which will be emitted is not known exactly, any strictly positive number (e.g. 1) will cause the RIP to proceed to open the %config% file rather than continuing to idle.
If there is no input pending, this function should return 0 (NOT -1 which would be an error condition), so that the RIP can continue to do any idle-time tasks allocated to it. It will then call bytesavailable at frequent intervals until there is some input pending. This is preferable to blocking either here or in the read or open functions when this condition arises.
|
static |
The open file routine for the config device type. See DEVICELIST_OPEN().
Since we are not implementing write functionality, it will be an error to attempt an open for other than reading. Also the semantics of the device mean that it does not make sense to have more than one file open at once for the whole device type, therefore this too is an error.
|
static |
The read_file routine for the config device type. See DEVICELIST_READ().
On the first read, we emit the PostScript required to set up the environment and set up the two files and true on the operand stack as described at the head of the file.
On the second call we return zero bytes which indicates end of file to the RIP.
|
static |
The file descriptor for config device.
enum { ... } config_status |
Used to maintain the state of the device between read calls.
For a more comprehensive implementation this would be considerably more complex since more than one buffer full of information may have to be returned by the read file function.
|
static |
The skin job timeline.