]>
Commit | Line | Data |
---|---|---|
74456259 | 1 | /* |
c9d3f842 | 2 | * "$Id$" |
74456259 | 3 | * |
725dbff8 | 4 | * Label printer filter for the Common UNIX Printing System (CUPS). |
74456259 | 5 | * |
c9d3f842 | 6 | * Copyright 2001-2005 by Easy Software Products. |
74456259 | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
c9d3f842 | 18 | * Hollywood, Maryland 20636 USA |
74456259 | 19 | * |
9639c4de | 20 | * Voice: (301) 373-9600 |
74456259 | 21 | * EMail: cups-info@cups.org |
22 | * WWW: http://www.cups.org | |
23 | * | |
dab1a4d8 | 24 | * This file is subject to the Apple OS-Developed Software exception. |
25 | * | |
74456259 | 26 | * Contents: |
27 | * | |
28 | * Setup() - Prepare the printer for printing. | |
29 | * StartPage() - Start a page of graphics. | |
30 | * EndPage() - Finish a page of graphics. | |
31 | * Shutdown() - Shutdown the printer. | |
32 | * CancelJob() - Cancel the current job... | |
74456259 | 33 | * OutputLine() - Output a line of graphics. |
34 | * main() - Main entry and processing of driver. | |
35 | */ | |
36 | ||
37 | /* | |
38 | * Include necessary headers... | |
39 | */ | |
40 | ||
41 | #include <cups/cups.h> | |
42 | #include <cups/string.h> | |
43 | #include "raster.h" | |
44 | #include <stdlib.h> | |
45 | #include <unistd.h> | |
46 | #include <fcntl.h> | |
47 | #include <signal.h> | |
48 | ||
49 | ||
725dbff8 | 50 | /* |
51 | * This driver filter currently supports Dymo and Zebra label printers. | |
52 | * | |
53 | * The Dymo portion of the driver has been tested with the 300, 330, | |
54 | * and 330 Turbo label printers; it may also work with older models. | |
55 | * The Dymo printers support printing at 136, 203, and 300 DPI. | |
56 | * | |
ea19a116 | 57 | * The Zebra portion of the driver has been tested with the LP-2844Z label |
725dbff8 | 58 | * printer; it may also work with other models. The driver supports both |
ea19a116 | 59 | * EPL and ZPL as defined in Zebra's on-line developer documentation. |
725dbff8 | 60 | */ |
61 | ||
62 | /* | |
63 | * Model number constants... | |
64 | */ | |
65 | ||
66 | #define DYMO_3x0 0 /* Dymo Labelwriter 300/330/330 Turbo */ | |
67 | ||
ea19a116 | 68 | #define ZEBRA_EPL_LINE 0x10 /* Zebra EPL line mode printers */ |
69 | #define ZEBRA_EPL_PAGE 0x11 /* Zebra EPL page mode printers */ | |
70 | #define ZEBRA_ZPL 0x12 /* Zebra ZPL-based printers */ | |
725dbff8 | 71 | |
72 | ||
74456259 | 73 | /* |
74 | * Globals... | |
75 | */ | |
76 | ||
77 | unsigned char *Buffer; /* Output buffer */ | |
725dbff8 | 78 | int ModelNumber, /* cupsModelNumber attribute */ |
79 | Page, /* Current page */ | |
80 | Feed, /* Number of lines to skip */ | |
ea19a116 | 81 | Canceled; /* Non-zero if job is canceled */ |
74456259 | 82 | |
83 | ||
84 | /* | |
85 | * Prototypes... | |
86 | */ | |
87 | ||
88 | void Setup(void); | |
89 | void StartPage(cups_page_header_t *header); | |
725dbff8 | 90 | void EndPage(cups_page_header_t *header); |
74456259 | 91 | void CancelJob(int sig); |
ea19a116 | 92 | void OutputLine(cups_page_header_t *header, int y); |
74456259 | 93 | |
94 | ||
95 | /* | |
96 | * 'Setup()' - Prepare the printer for printing. | |
97 | */ | |
98 | ||
99 | void | |
100 | Setup(void) | |
101 | { | |
725dbff8 | 102 | int i; /* Looping var */ |
103 | ppd_file_t *ppd; /* PPD file */ | |
74456259 | 104 | |
105 | ||
106 | /* | |
725dbff8 | 107 | * Get the model number from the PPD file... |
74456259 | 108 | */ |
109 | ||
725dbff8 | 110 | if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) |
111 | { | |
112 | ModelNumber = ppd->model_number; | |
113 | ppdClose(ppd); | |
114 | } | |
c67094f2 | 115 | |
116 | /* | |
725dbff8 | 117 | * Initialize based on the model number... |
c67094f2 | 118 | */ |
119 | ||
725dbff8 | 120 | switch (ModelNumber) |
121 | { | |
122 | case DYMO_3x0 : | |
123 | /* | |
124 | * Clear any remaining data... | |
125 | */ | |
126 | ||
127 | for (i = 0; i < 100; i ++) | |
128 | putchar(0x1b); | |
129 | ||
130 | /* | |
131 | * Reset the printer... | |
132 | */ | |
133 | ||
134 | fputs("\033@", stdout); | |
135 | break; | |
136 | ||
ea19a116 | 137 | case ZEBRA_EPL_LINE : |
138 | break; | |
139 | ||
140 | case ZEBRA_EPL_PAGE : | |
141 | break; | |
142 | ||
725dbff8 | 143 | case ZEBRA_ZPL : |
725dbff8 | 144 | break; |
145 | } | |
74456259 | 146 | } |
147 | ||
148 | ||
149 | /* | |
150 | * 'StartPage()' - Start a page of graphics. | |
151 | */ | |
152 | ||
153 | void | |
154 | StartPage(cups_page_header_t *header) /* I - Page header */ | |
155 | { | |
9a12ff91 | 156 | int length; /* Actual label length */ |
74456259 | 157 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) |
158 | struct sigaction action; /* Actions for POSIX signals */ | |
159 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ | |
160 | ||
161 | ||
162 | /* | |
163 | * Register a signal handler to eject the current page if the | |
ea19a116 | 164 | * job is canceled. |
74456259 | 165 | */ |
166 | ||
167 | #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ | |
168 | sigset(SIGTERM, CancelJob); | |
169 | #elif defined(HAVE_SIGACTION) | |
170 | memset(&action, 0, sizeof(action)); | |
171 | ||
172 | sigemptyset(&action.sa_mask); | |
173 | action.sa_handler = CancelJob; | |
174 | sigaction(SIGTERM, &action, NULL); | |
175 | #else | |
176 | signal(SIGTERM, CancelJob); | |
177 | #endif /* HAVE_SIGSET */ | |
178 | ||
725dbff8 | 179 | switch (ModelNumber) |
180 | { | |
181 | case DYMO_3x0 : | |
182 | /* | |
183 | * Setup printer/job attributes... | |
184 | */ | |
185 | ||
186 | length = header->PageSize[1] * header->HWResolution[1] / 72; | |
187 | ||
188 | printf("\033L%c%c", length >> 8, length); | |
189 | printf("\033D%c", header->cupsBytesPerLine); | |
190 | ||
191 | printf("\033%c", header->cupsCompression + 'c'); /* Darkness */ | |
192 | break; | |
74456259 | 193 | |
ea19a116 | 194 | case ZEBRA_EPL_LINE : |
195 | /* | |
196 | * Set darkness... | |
197 | */ | |
198 | ||
199 | printf("D%d", 7 * header->cupsCompression / 100); | |
200 | ||
201 | /* | |
202 | * Start buffered output... | |
203 | */ | |
204 | ||
205 | putchar('B'); | |
206 | break; | |
207 | ||
208 | case ZEBRA_EPL_PAGE : | |
209 | /* | |
210 | * Set darkness... | |
211 | */ | |
212 | ||
213 | printf("D%d", 15 * header->cupsCompression / 100); | |
214 | ||
215 | /* | |
216 | * Set label size... | |
217 | */ | |
218 | ||
219 | printf("q%d\n", header->cupsWidth); | |
220 | break; | |
221 | ||
725dbff8 | 222 | case ZEBRA_ZPL : |
725dbff8 | 223 | /* |
224 | * Set darkness... | |
225 | */ | |
9a12ff91 | 226 | |
ea19a116 | 227 | printf("~SD%02d\n", 30 * header->cupsCompression / 100); |
74456259 | 228 | |
725dbff8 | 229 | /* |
230 | * Start bitmap graphics... | |
231 | */ | |
232 | ||
233 | printf("~DGR:CUPS.GRF,%d,%d,\n", | |
234 | header->cupsHeight * header->cupsBytesPerLine, | |
235 | header->cupsBytesPerLine); | |
236 | break; | |
237 | } | |
74456259 | 238 | |
239 | /* | |
240 | * Allocate memory for a line of graphics... | |
241 | */ | |
242 | ||
243 | Buffer = malloc(header->cupsBytesPerLine); | |
244 | Feed = 0; | |
245 | } | |
246 | ||
247 | ||
248 | /* | |
249 | * 'EndPage()' - Finish a page of graphics. | |
250 | */ | |
251 | ||
252 | void | |
725dbff8 | 253 | EndPage(cups_page_header_t *header) /* I - Page header */ |
74456259 | 254 | { |
255 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) | |
725dbff8 | 256 | struct sigaction action; /* Actions for POSIX signals */ |
74456259 | 257 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ |
258 | ||
259 | ||
725dbff8 | 260 | switch (ModelNumber) |
261 | { | |
262 | case DYMO_3x0 : | |
263 | /* | |
264 | * Eject the current page... | |
265 | */ | |
266 | ||
267 | fputs("\033E", stdout); | |
ea19a116 | 268 | break; |
74456259 | 269 | |
ea19a116 | 270 | case ZEBRA_EPL_LINE : |
271 | /* | |
272 | * End buffered output, eject the label... | |
273 | */ | |
274 | ||
275 | putchar('E'); | |
276 | break; | |
277 | ||
278 | case ZEBRA_EPL_PAGE : | |
279 | /* | |
280 | * Print the label... | |
281 | */ | |
282 | ||
283 | puts("P1"); | |
725dbff8 | 284 | break; |
285 | ||
286 | case ZEBRA_ZPL : | |
ea19a116 | 287 | if (Canceled) |
725dbff8 | 288 | { |
289 | /* | |
290 | * Cancel bitmap download... | |
291 | */ | |
292 | ||
293 | puts("~DN"); | |
294 | break; | |
295 | } | |
296 | ||
297 | /* | |
ea19a116 | 298 | * Start label, set origin to 1/8,1/16", and set length... |
725dbff8 | 299 | */ |
74456259 | 300 | |
725dbff8 | 301 | puts("^XA"); |
ea19a116 | 302 | printf("^LH%d,%d\n", header->HWResolution[0] / 8, |
303 | header->HWResolution[1] / 16); | |
725dbff8 | 304 | printf("^LL%d\n", header->cupsHeight); |
305 | ||
306 | /* | |
307 | * Cut labels if requested... | |
308 | */ | |
309 | ||
310 | if (header->CutMedia) | |
311 | puts("^MMC"); | |
ea19a116 | 312 | else |
313 | puts("^MMT"); | |
725dbff8 | 314 | |
315 | /* | |
316 | * Display the label image... | |
317 | */ | |
318 | ||
319 | puts("~FO0,0^XGR:CUPS.GRF,1,1^FS"); | |
320 | ||
321 | /* | |
322 | * End the label and eject... | |
323 | */ | |
324 | ||
325 | puts("^XZ"); | |
326 | break; | |
327 | } | |
74456259 | 328 | |
ea19a116 | 329 | fflush(stdout); |
330 | ||
74456259 | 331 | /* |
332 | * Unregister the signal handler... | |
333 | */ | |
334 | ||
335 | #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ | |
336 | sigset(SIGTERM, SIG_IGN); | |
337 | #elif defined(HAVE_SIGACTION) | |
338 | memset(&action, 0, sizeof(action)); | |
339 | ||
340 | sigemptyset(&action.sa_mask); | |
341 | action.sa_handler = SIG_IGN; | |
342 | sigaction(SIGTERM, &action, NULL); | |
343 | #else | |
344 | signal(SIGTERM, SIG_IGN); | |
345 | #endif /* HAVE_SIGSET */ | |
346 | ||
347 | /* | |
348 | * Free memory... | |
349 | */ | |
350 | ||
351 | free(Buffer); | |
352 | } | |
353 | ||
354 | ||
355 | /* | |
356 | * 'CancelJob()' - Cancel the current job... | |
357 | */ | |
358 | ||
359 | void | |
360 | CancelJob(int sig) /* I - Signal */ | |
361 | { | |
725dbff8 | 362 | /* |
363 | * Tell the main loop to stop... | |
364 | */ | |
74456259 | 365 | |
366 | (void)sig; | |
367 | ||
ea19a116 | 368 | Canceled = 1; |
725dbff8 | 369 | } |
74456259 | 370 | |
74456259 | 371 | |
725dbff8 | 372 | /* |
373 | * 'OutputLine()' - Output a line of graphics... | |
374 | */ | |
375 | ||
376 | void | |
ea19a116 | 377 | OutputLine(cups_page_header_t *header, /* I - Page header */ |
378 | int y) /* I - Line number */ | |
725dbff8 | 379 | { |
380 | int i; /* Looping var */ | |
381 | unsigned char *ptr; /* Pointer into buffer */ | |
382 | ||
74456259 | 383 | |
725dbff8 | 384 | switch (ModelNumber) |
385 | { | |
386 | case DYMO_3x0 : | |
387 | /* | |
388 | * See if the line is blank; if not, write it to the printer... | |
389 | */ | |
390 | ||
391 | if (Buffer[0] || | |
392 | memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1)) | |
393 | { | |
394 | if (Feed) | |
395 | { | |
396 | while (Feed > 255) | |
397 | { | |
398 | printf("\033f\001%c", 255); | |
399 | Feed -= 255; | |
400 | } | |
401 | ||
402 | printf("\033f\001%c", Feed); | |
403 | Feed = 0; | |
404 | } | |
74456259 | 405 | |
725dbff8 | 406 | putchar(0x16); |
407 | fwrite(Buffer, header->cupsBytesPerLine, 1, stdout); | |
408 | fflush(stdout); | |
409 | ||
410 | #ifdef __sgi | |
411 | /* | |
412 | * This hack works around a bug in the IRIX serial port driver when | |
413 | * run at high baud rates (e.g. 115200 baud)... This results in | |
414 | * slightly slower label printing, but at least the labels come | |
415 | * out properly. | |
416 | */ | |
417 | ||
418 | sginap(1); | |
419 | #endif /* __sgi */ | |
420 | } | |
421 | else | |
422 | Feed ++; | |
423 | break; | |
424 | ||
ea19a116 | 425 | case ZEBRA_EPL_LINE : |
426 | printf("g%03d", header->cupsBytesPerLine); | |
427 | fwrite(Buffer, 1, header->cupsBytesPerLine, stdout); | |
428 | fflush(stdout); | |
429 | break; | |
430 | ||
431 | case ZEBRA_EPL_PAGE : | |
432 | printf("GW0,%d,%d,1", y, header->cupsBytesPerLine); | |
433 | fwrite(Buffer, 1, header->cupsBytesPerLine, stdout); | |
434 | putchar('\n'); | |
435 | fflush(stdout); | |
436 | break; | |
437 | ||
725dbff8 | 438 | case ZEBRA_ZPL : |
725dbff8 | 439 | for (i = header->cupsBytesPerLine, ptr = Buffer; i > 0; i --, ptr ++) |
725dbff8 | 440 | if (!*ptr && (i == 1 || !memcmp(ptr, ptr + 1, i - 1))) |
441 | { | |
442 | putchar(','); | |
443 | break; | |
444 | } | |
445 | else | |
725dbff8 | 446 | printf("%02X", *ptr); |
447 | ||
448 | putchar('\n'); | |
449 | break; | |
450 | } | |
74456259 | 451 | } |
452 | ||
453 | ||
454 | /* | |
455 | * 'main()' - Main entry and processing of driver. | |
456 | */ | |
457 | ||
725dbff8 | 458 | int /* O - Exit status */ |
459 | main(int argc, /* I - Number of command-line arguments */ | |
460 | char *argv[]) /* I - Command-line arguments */ | |
74456259 | 461 | { |
725dbff8 | 462 | int fd; /* File descriptor */ |
463 | cups_raster_t *ras; /* Raster stream for printing */ | |
464 | cups_page_header_t header; /* Page header from file */ | |
465 | int y; /* Current line */ | |
74456259 | 466 | |
467 | ||
468 | /* | |
469 | * Make sure status messages are not buffered... | |
470 | */ | |
471 | ||
472 | setbuf(stderr, NULL); | |
473 | ||
474 | /* | |
475 | * Check command-line... | |
476 | */ | |
477 | ||
478 | if (argc < 6 || argc > 7) | |
479 | { | |
480 | /* | |
481 | * We don't have the correct number of arguments; write an error message | |
482 | * and return. | |
483 | */ | |
484 | ||
485 | fputs("ERROR: rastertodymo job-id user title copies options [file]\n", stderr); | |
486 | return (1); | |
487 | } | |
488 | ||
489 | /* | |
490 | * Open the page stream... | |
491 | */ | |
492 | ||
493 | if (argc == 7) | |
494 | { | |
725dbff8 | 495 | if ((fd = open(argv[6], O_RDONLY)) == -1) |
74456259 | 496 | { |
497 | perror("ERROR: Unable to open raster file - "); | |
498 | sleep(1); | |
499 | return (1); | |
500 | } | |
501 | } | |
502 | else | |
2e32fcdb | 503 | fd = 0; |
74456259 | 504 | |
2e32fcdb | 505 | ras = cupsRasterOpen(fd, CUPS_RASTER_READ); |
74456259 | 506 | |
507 | /* | |
508 | * Initialize the print device... | |
509 | */ | |
510 | ||
511 | Setup(); | |
512 | ||
513 | /* | |
514 | * Process pages as needed... | |
515 | */ | |
516 | ||
725dbff8 | 517 | Page = 0; |
ea19a116 | 518 | Canceled = 0; |
74456259 | 519 | |
520 | while (cupsRasterReadHeader(ras, &header)) | |
521 | { | |
522 | /* | |
523 | * Write a status message with the page number and number of copies. | |
524 | */ | |
525 | ||
526 | Page ++; | |
527 | ||
528 | fprintf(stderr, "PAGE: %d 1\n", Page); | |
529 | ||
530 | /* | |
531 | * Start the page... | |
532 | */ | |
533 | ||
534 | StartPage(&header); | |
535 | ||
536 | /* | |
537 | * Loop for each line on the page... | |
538 | */ | |
539 | ||
ea19a116 | 540 | for (y = 0; y < header.cupsHeight && !Canceled; y ++) |
74456259 | 541 | { |
542 | /* | |
543 | * Let the user know how far we have progressed... | |
544 | */ | |
545 | ||
546 | if ((y & 15) == 0) | |
547 | fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page, | |
548 | 100 * y / header.cupsHeight); | |
549 | ||
550 | /* | |
551 | * Read a line of graphics... | |
552 | */ | |
553 | ||
554 | if (cupsRasterReadPixels(ras, Buffer, header.cupsBytesPerLine) < 1) | |
555 | break; | |
556 | ||
557 | /* | |
725dbff8 | 558 | * Write it to the printer... |
74456259 | 559 | */ |
560 | ||
ea19a116 | 561 | OutputLine(&header, y); |
74456259 | 562 | } |
563 | ||
564 | /* | |
565 | * Eject the page... | |
566 | */ | |
567 | ||
bbf6bc56 | 568 | EndPage(&header); |
725dbff8 | 569 | |
ea19a116 | 570 | if (Canceled) |
725dbff8 | 571 | break; |
74456259 | 572 | } |
573 | ||
574 | /* | |
575 | * Close the raster stream... | |
576 | */ | |
577 | ||
578 | cupsRasterClose(ras); | |
725dbff8 | 579 | if (fd != 0) |
2e32fcdb | 580 | close(fd); |
74456259 | 581 | |
582 | /* | |
583 | * If no pages were printed, send an error message... | |
584 | */ | |
585 | ||
586 | if (Page == 0) | |
587 | fputs("ERROR: No pages found!\n", stderr); | |
588 | else | |
725dbff8 | 589 | fputs("INFO: Ready to print.\n", stderr); |
74456259 | 590 | |
591 | return (Page == 0); | |
592 | } | |
593 | ||
594 | ||
595 | /* | |
c9d3f842 | 596 | * End of "$Id$". |
74456259 | 597 | */ |