1 /* GTK - The GIMP Toolkit
2 * gtkprintbackendpapi.c: Default implementation of GtkPrintBackend
4 * Copyright (C) 2003, Red Hat, Inc.
5 * Copyright (C) 2009, Sun Microsystems, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/types.h>
34 #include <glib/gi18n-lib.h>
37 #include "gtkprintbackendpapi.h"
38 #include "gtkprinterpapi.h"
39 #include "gtkprinter-private.h"
41 typedef struct _GtkPrintBackendPapiClass GtkPrintBackendPapiClass;
43 #define GTK_PRINT_BACKEND_PAPI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_PAPI, GtkPrintBackendPapiClass))
44 #define GTK_IS_PRINT_BACKEND_PAPI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_PAPI))
45 #define GTK_PRINT_BACKEND_PAPI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_PAPI, GtkPrintBackendPapiClass))
47 #define _PAPI_MAX_CHUNK_SIZE 8192
49 static GType print_backend_papi_type = 0;
51 struct _GtkPrintBackendPapiClass
53 GtkPrintBackendClass parent_class;
56 struct _GtkPrintBackendPapi
58 GtkPrintBackend parent_instance;
60 char *default_printer;
67 static GObjectClass *backend_parent_class;
69 static void gtk_print_backend_papi_class_init (GtkPrintBackendPapiClass *class);
70 static void gtk_print_backend_papi_init (GtkPrintBackendPapi *impl);
71 static void gtk_print_backend_papi_finalize (GObject *object);
72 static void gtk_print_backend_papi_dispose (GObject *object);
73 static void papi_request_printer_list (GtkPrintBackend *print_backend);
74 static gboolean papi_get_printer_list (GtkPrintBackendPapi *papi_backend);
75 static void papi_printer_request_details (GtkPrinter *printer);
76 static GtkPrintCapabilities papi_printer_get_capabilities (GtkPrinter *printer);
77 static void papi_printer_get_settings_from_options (GtkPrinter *printer,
78 GtkPrinterOptionSet *options,
79 GtkPrintSettings *settings);
80 static GtkPrinterOptionSet *papi_printer_get_options (GtkPrinter *printer,
81 GtkPrintSettings *settings,
82 GtkPageSetup *page_setup,
83 GtkPrintCapabilities capabilities);
84 static void papi_printer_prepare_for_print (GtkPrinter *printer,
85 GtkPrintJob *print_job,
86 GtkPrintSettings *settings,
87 GtkPageSetup *page_setup);
88 static cairo_surface_t * papi_printer_create_cairo_surface (GtkPrinter *printer,
89 GtkPrintSettings *settings,
92 GIOChannel *cache_io);
93 static void gtk_print_backend_papi_print_stream (GtkPrintBackend *print_backend,
96 GtkPrintJobCompleteFunc callback,
98 GDestroyNotify dnotify);
100 static gboolean papi_display_printer_status (gpointer user_data);
101 static void papi_display_printer_status_done (gpointer user_data);
104 gtk_print_backend_papi_register_type (GTypeModule *module)
106 const GTypeInfo print_backend_papi_info =
108 sizeof (GtkPrintBackendPapiClass),
109 NULL, /* base_init */
110 NULL, /* base_finalize */
111 (GClassInitFunc) gtk_print_backend_papi_class_init,
112 NULL, /* class_finalize */
113 NULL, /* class_data */
114 sizeof (GtkPrintBackendPapi),
116 (GInstanceInitFunc) gtk_print_backend_papi_init,
119 print_backend_papi_type = g_type_module_register_type (module,
120 GTK_TYPE_PRINT_BACKEND,
121 "GtkPrintBackendPapi",
122 &print_backend_papi_info, 0);
126 pb_module_init (GTypeModule *module)
128 gtk_print_backend_papi_register_type (module);
129 gtk_printer_papi_register_type (module);
133 pb_module_exit (void)
138 G_MODULE_EXPORT GtkPrintBackend *
139 pb_module_create (void)
141 return gtk_print_backend_papi_new ();
145 * GtkPrintBackendPapi
148 gtk_print_backend_papi_get_type (void)
150 return print_backend_papi_type;
154 * gtk_print_backend_papi_new:
156 * Creates a new #GtkPrintBackendPapi object. #GtkPrintBackendPapi
157 * implements the #GtkPrintBackend interface with direct access to
158 * the filesystem using Unix/Linux API calls
160 * Return value: the new #GtkPrintBackendPapi object
163 gtk_print_backend_papi_new (void)
165 return g_object_new (GTK_TYPE_PRINT_BACKEND_PAPI, NULL);
169 gtk_print_backend_papi_class_init (GtkPrintBackendPapiClass *class)
171 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
172 GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
174 backend_parent_class = g_type_class_peek_parent (class);
176 gobject_class->finalize = gtk_print_backend_papi_finalize;
177 gobject_class->dispose = gtk_print_backend_papi_dispose;
179 backend_class->request_printer_list = papi_request_printer_list;
180 backend_class->printer_request_details = papi_printer_request_details;
181 backend_class->printer_get_capabilities = papi_printer_get_capabilities;
182 backend_class->printer_get_options = papi_printer_get_options;
183 backend_class->printer_get_settings_from_options = papi_printer_get_settings_from_options;
184 backend_class->printer_prepare_for_print = papi_printer_prepare_for_print;
185 backend_class->printer_create_cairo_surface = papi_printer_create_cairo_surface;
186 backend_class->print_stream = gtk_print_backend_papi_print_stream;
189 static cairo_status_t
190 _cairo_write (void *closure,
191 const unsigned char *data,
194 GIOChannel *io = (GIOChannel *)closure;
196 GError *error = NULL;
199 g_print ("PAPI Backend: Writting %i byte chunk to temp file\n", length));
203 g_io_channel_write_chars (io, (char *)data, length, &written, &error);
208 g_print ("PAPI Backend: Error writting to temp file, %s\n", error->message));
210 g_error_free (error);
211 return CAIRO_STATUS_WRITE_ERROR;
215 g_print ("PAPI Backend: Wrote %i bytes to temp file\n", written));
221 return CAIRO_STATUS_SUCCESS;
224 static cairo_surface_t *
225 papi_printer_create_cairo_surface (GtkPrinter *printer,
226 GtkPrintSettings *settings,
229 GIOChannel *cache_io)
231 cairo_surface_t *surface;
233 surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
235 cairo_surface_set_fallback_resolution (surface,
236 2.0 * gtk_print_settings_get_printer_lpi (settings),
237 2.0 * gtk_print_settings_get_printer_lpi (settings));
243 GtkPrintBackend *backend;
244 GtkPrintJobCompleteFunc callback;
247 GDestroyNotify dnotify;
249 papi_service_t service;
250 papi_stream_t stream;
254 papi_print_cb (GtkPrintBackendPapi *print_backend,
258 _PrintStreamData *ps = (_PrintStreamData *) user_data;
261 ps->callback (ps->job, ps->user_data, error);
264 ps->dnotify (ps->user_data);
266 gtk_print_job_set_status (ps->job,
267 error ? GTK_PRINT_STATUS_FINISHED_ABORTED
268 : GTK_PRINT_STATUS_FINISHED);
271 g_object_unref (ps->job);
277 papi_write (GIOChannel *source,
281 gchar buf[_PAPI_MAX_CHUNK_SIZE];
285 _PrintStreamData *ps = (_PrintStreamData *) user_data;
286 papi_job_t job = NULL;
289 status = g_io_channel_read_chars (source,
291 _PAPI_MAX_CHUNK_SIZE,
295 /* Keep writing to PAPI input stream while there are data */
296 if (status != G_IO_STATUS_ERROR)
298 papiJobStreamWrite (ps->service, ps->stream, buf, bytes_read);
301 /* Finish reading input stream data. Closing the stream and handle to service */
302 if (bytes_read == 0) {
303 papiJobStreamClose (ps->service, ps->stream, &job);
306 papiServiceDestroy (ps->service);
310 if (error != NULL || status == G_IO_STATUS_EOF)
312 papi_print_cb (GTK_PRINT_BACKEND_PAPI (ps->backend),
316 g_error_free (error);
321 g_print ("PAPI Backend: %s\n", error->message));
323 g_error_free (error);
330 g_print ("PAPI Backend: Writting %i byte chunk to papi pipe\n", bytes_read));
336 gtk_print_backend_papi_print_stream (GtkPrintBackend *print_backend,
339 GtkPrintJobCompleteFunc callback,
341 GDestroyNotify dnotify)
343 GError *print_error = NULL;
344 GtkPrinterPapi *printer;
345 _PrintStreamData *ps;
346 GtkPrintSettings *settings;
353 papi_status_t pstatus = NULL;
354 papi_attribute_t **attrs = NULL;
355 papi_job_ticket_t *ticket = NULL;
357 printer = GTK_PRINTER_PAPI (gtk_print_job_get_printer (job));
358 settings = gtk_print_job_get_settings (job);
360 /* FIXME - the title should be set as the job-name */
361 title = gtk_print_job_get_title (job);
363 ps = g_new0 (_PrintStreamData, 1);
364 ps->callback = callback;
365 ps->user_data = user_data;
366 ps->dnotify = dnotify;
367 ps->job = g_object_ref (job);
371 /* This cannot be queried yet with the current API */
372 papiAttributeListAddString (&attrs, PAPI_ATTR_EXCL, "document-format", "application/postscript");
373 val = gtk_print_settings_get_duplex (settings) ;
374 if (val == GTK_PRINT_DUPLEX_HORIZONTAL)
375 papiAttributeListAddString (&attrs, PAPI_ATTR_EXCL, "Duplex", "DuplexNoTumble");
376 else if (val == GTK_PRINT_DUPLEX_VERTICAL)
377 papiAttributeListAddString (&attrs, PAPI_ATTR_EXCL, "Duplex", "DuplexTumble");
379 if (job->num_copies > 1)
381 papiAttributeListAddInteger (&attrs, PAPI_ATTR_EXCL, "copies", job->num_copies);
384 prtnm = strdup (gtk_printer_get_name (GTK_PRINTER(printer)));
386 if (papiServiceCreate (&(ps->service), prtnm, NULL, NULL, NULL,
387 PAPI_ENCRYPT_NEVER, NULL) != PAPI_OK)
390 pstatus = papiJobStreamOpen (ps->service, prtnm, attrs, ticket, &(ps->stream));
391 if (pstatus != PAPI_OK)
393 papiServiceDestroy (ps->service);
398 /* Everything set up fine, so get ready to wait for input data stream */
399 g_io_add_watch (data_io,
400 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
401 (GIOFunc) papi_write,
407 _papi_set_default_printer (GtkPrintBackendPapi *backend)
409 char *def_printer = NULL;
410 char *_default_attr[] = { "printer-name", NULL };
411 papi_service_t service = NULL;
412 papi_printer_t default_printer = NULL;
413 papi_attribute_t **attrs = NULL;
415 if (papiServiceCreate (&service, NULL, NULL, NULL, NULL, PAPI_ENCRYPT_NEVER,
419 if (papiPrinterQuery (service, "_default", _default_attr, NULL,
420 &default_printer) == PAPI_OK)
422 if (default_printer != NULL)
424 attrs = papiPrinterGetAttributeList (default_printer);
427 if (papiAttributeListGetString (attrs, NULL, "printer-name",
428 &def_printer) == PAPI_OK)
430 backend->default_printer = strdup (def_printer);
435 papiPrinterFree (default_printer);
436 papiServiceDestroy (service);
440 gtk_print_backend_papi_init (GtkPrintBackendPapi *backend)
442 _papi_set_default_printer (backend);
446 gtk_print_backend_papi_finalize (GObject *object)
448 GtkPrintBackendPapi *backend_papi;
451 g_print ("PAPI Backend: finalizing PAPI backend module\n"));
453 backend_papi = GTK_PRINT_BACKEND_PAPI (object);
455 g_free (backend_papi->default_printer);
456 backend_papi->default_printer = NULL;
458 backend_parent_class->finalize (object);
463 gtk_print_backend_papi_dispose (GObject *object)
465 GtkPrintBackendPapi *backend_papi;
468 g_print ("PAPI Backend: %s\n", G_STRFUNC));
470 backend_papi = GTK_PRINT_BACKEND_PAPI (object);
472 backend_parent_class->dispose (object);
476 get_all_list(papi_service_t svc)
478 papi_status_t status;
479 papi_printer_t printer = NULL;
480 char *attr[] = { "member-names", NULL };
483 status = papiPrinterQuery(svc, "_all", attr, NULL, &printer);
484 if ((status == PAPI_OK) && (printer != NULL)) {
485 papi_attribute_t **attributes =
486 papiPrinterGetAttributeList(printer);
487 if (attributes != NULL) {
491 for (status = papiAttributeListGetString(attributes,
492 &iter, "member-names", &member);
494 status = papiAttributeListGetString(attributes,
495 &iter, NULL, &member))
496 list_append(&names, strdup(member));
498 papiPrinterFree(printer);
505 get_printers_list(papi_service_t svc)
507 papi_status_t status;
508 papi_printer_t *printers = NULL;
509 char *keys[] = { "printer-name", "printer-uri-supported", NULL };
512 status = papiPrintersList(svc, keys, NULL, &printers);
513 if ((status == PAPI_OK) && (printers != NULL)) {
516 for (i = 0; printers[i] != NULL; i++) {
517 papi_attribute_t **attributes =
518 papiPrinterGetAttributeList(printers[i]);
521 (void) papiAttributeListGetString(attributes, NULL,
522 "printer-name", &name);
523 if ((name != NULL) && (strcmp(name, "_default") != 0))
524 list_append(&names, strdup(name));
526 papiPrinterListFree(printers);
533 papi_request_printer_list (GtkPrintBackend *backend)
535 GtkPrintBackendPapi *papi_backend;
537 papi_backend = GTK_PRINT_BACKEND_PAPI (backend);
539 /* Get the list of printers using papi API */
540 papi_get_printer_list (papi_backend);
544 papi_get_printer_list (GtkPrintBackendPapi *papi_backend)
547 const char *attributes[] = /* Attributes we're interested in */
550 "printer-uri-supported",
553 papi_status_t status, status2;
554 papi_service_t service = NULL;
555 char **printers = NULL;
557 GtkPrinterPapi *papi_printer;
558 GList *current_printer_list;
559 GtkPrintBackend *backend = GTK_PRINT_BACKEND (papi_backend);
561 if ((status = papiServiceCreate (&service, NULL, NULL, NULL, NULL,
562 PAPI_ENCRYPT_NEVER, NULL)) != PAPI_OK)
565 if ((printers = get_all_list (service)) == NULL)
567 printers = get_printers_list (service);
570 if (printers == NULL)
572 papiServiceDestroy (service);
576 for (i = 0; printers[i] != NULL; i++)
579 char *name = NULL, *url = NULL;
580 papi_attribute_t **attrs = NULL;
582 printer = gtk_print_backend_find_printer (backend, printers[i]);
586 /* skip null printer name just in case */
587 if (printers[i] == NULL)
590 /* skip the alias _default and _all printers */
591 if (strcmp(printers[i], "_default")==0 || strcmp(printers[i], "_all")==0)
594 papi_printer = gtk_printer_papi_new (printers[i], backend);
595 printer = GTK_PRINTER (papi_printer);
597 /* Only marked default printer to not have details so that
598 the request_details method will be called at start up
601 if (papi_backend->default_printer != NULL)
602 if (strcmp (printers[i], papi_backend->default_printer)==0)
604 gtk_printer_set_is_default (printer, TRUE);
607 gtk_printer_set_icon_name (printer, "printer");
608 gtk_print_backend_add_printer (backend, printer);
609 gtk_printer_set_is_active (printer, TRUE);
611 /* gtk_printer_set_has_details (printer, TRUE); */
614 g_object_ref (printer);
616 if (!gtk_printer_is_active (printer))
618 gtk_printer_set_is_active (printer, TRUE);
619 gtk_printer_set_is_new (printer, TRUE);
622 if (gtk_printer_is_new (printer))
624 g_signal_emit_by_name (backend, "printer-added", printer);
625 gtk_printer_set_is_new (printer, FALSE);
628 g_object_unref (printer);
632 papiServiceDestroy (service);
634 /* To set that the list of printers added is complete */
635 gtk_print_backend_set_list_done (backend);
641 update_printer_status (GtkPrinter *printer)
643 GtkPrintBackend *backend;
644 GtkPrinterPapi *papi_printer;
645 gboolean status_changed = FALSE;
647 backend = gtk_printer_get_backend (printer);
648 papi_printer = GTK_PRINTER_PAPI (printer);
650 /* if (status_changed) */
651 g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
652 "printer-status-changed", printer);
657 static GtkPrinterOptionSet *
658 papi_printer_get_options (GtkPrinter *printer,
659 GtkPrintSettings *settings,
660 GtkPageSetup *page_setup,
661 GtkPrintCapabilities capabilities)
663 GtkPrinterOptionSet *set;
664 GtkPrinterOption *option;
666 char *print_at[] = { "now", "on-hold" };
667 char *n_up[] = {"1"};
669 /* Update the printer status before the printer options are displayed */
670 update_printer_status (printer);
672 set = gtk_printer_option_set_new ();
674 /* non-ppd related settings */
676 /* This maps to number-up-supported in PAPI. FIXME
677 * number-up-default is the default value.
678 * number-up-supported is the list of number of able to print per page
680 option = gtk_printer_option_new ("gtk-n-up", "Pages Per Sheet", GTK_PRINTER_OPTION_TYPE_PICKONE);
681 gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up),
683 gtk_printer_option_set (option, "1");
684 gtk_printer_option_set_add (set, option);
685 g_object_unref (option);
687 /* This maps to job-priority-supported and job-priority-default in PAPI - FIXME*/
689 /* This relates to job-sheets-supported in PAPI FIXME*/
691 /* This relates to job-hold-until-supported in PAPI */
692 option = gtk_printer_option_new ("gtk-print-time", "Print at", GTK_PRINTER_OPTION_TYPE_PICKONE);
693 gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (print_at),
695 gtk_printer_option_set (option, "now");
696 gtk_printer_option_set_add (set, option);
697 g_object_unref (option);
703 papi_printer_get_settings_from_options (GtkPrinter *printer,
704 GtkPrinterOptionSet *options,
705 GtkPrintSettings *settings)
707 GtkPrinterOption *option;
709 option = gtk_printer_option_set_lookup (options, "gtk-n-up");
711 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP, option->value);
716 papi_printer_prepare_for_print (GtkPrinter *printer,
717 GtkPrintJob *print_job,
718 GtkPrintSettings *settings,
719 GtkPageSetup *page_setup)
723 GtkPaperSize *papersize = NULL;
724 char *ppd_paper_name;
726 print_job->print_pages = gtk_print_settings_get_print_pages (settings);
727 print_job->page_ranges = NULL;
728 print_job->num_page_ranges = 0;
730 if (print_job->print_pages == GTK_PRINT_PAGES_RANGES)
731 print_job->page_ranges =
732 gtk_print_settings_get_page_ranges (settings,
733 &print_job->num_page_ranges);
735 print_job->collate = gtk_print_settings_get_collate (settings);
736 print_job->reverse = gtk_print_settings_get_reverse (settings);
737 print_job->num_copies = gtk_print_settings_get_n_copies (settings);
739 scale = gtk_print_settings_get_scale (settings);
741 print_job->scale = scale/100.0;
743 papersize = gtk_page_setup_get_paper_size (page_setup);
744 ppd_paper_name = gtk_paper_size_get_ppd_name (papersize);
746 page_set = gtk_print_settings_get_page_set (settings);
747 if (page_set == GTK_PAGE_SET_EVEN)
748 print_job->page_set = GTK_PAGE_SET_EVEN;
749 else if (page_set == GTK_PAGE_SET_ODD)
750 print_job->page_set = GTK_PAGE_SET_ODD;
752 print_job->page_set = GTK_PAGE_SET_ALL;
754 print_job->rotate_to_orientation = TRUE;
759 is_local_printer (gchar *printer_uri)
761 if (strncmp (printer_uri, "lpsched:", 8) == 0)
768 merge_ppd_data (papi_attribute_t ***attributes, gchar *ppdfile)
770 get_ppd_attrs (attributes, ppdfile);
775 papi_display_printer_status_done (gpointer user_data)
777 GtkPrinter *printer = (GtkPrinter *) user_data;
778 GtkPrinterPapi *papi_printer;
780 g_signal_emit_by_name (printer, "details-acquired", TRUE);
781 papi_printer = GTK_PRINTER_PAPI (printer);
789 papi_display_printer_status (gpointer user_data)
791 GtkPrinter *printer = (GtkPrinter *) user_data;
792 GtkPrinterPapi *papi_printer;
793 gchar *loc, *printer_uri, *ppdfile;
795 papi_service_t service;
796 papi_attribute_t **attrs = NULL;
797 papi_printer_t current_printer = NULL;
798 static int count = 0;
800 papi_printer = GTK_PRINTER_PAPI (printer);
801 if (papiServiceCreate (&service, NULL, NULL, NULL, NULL, PAPI_ENCRYPT_NEVER,
803 return G_SOURCE_REMOVE;
805 if (papiPrinterQuery (service, papi_printer->printer_name, NULL, NULL,
806 ¤t_printer) != PAPI_OK)
809 gtk_printer_set_state_message (printer, _("printer offline"));
812 if (current_printer != NULL)
814 attrs = papiPrinterGetAttributeList (current_printer);
817 if (papiAttributeListGetString (attrs, NULL, "printer-info", &loc) == PAPI_OK)
819 gtk_printer_set_location (printer, loc);
822 if (papiAttributeListGetInteger (attrs, NULL, "printer-state", &state) == PAPI_OK)
827 case IDLE: gtk_printer_set_state_message (printer, _("ready to print"));
830 case PROCESSING: gtk_printer_set_state_message (printer, _("processing job"));
834 case STOPPED: gtk_printer_set_state_message (printer, _("paused"));
837 default: gtk_printer_set_state_message (printer, _("unknown"));
842 papiPrinterFree (current_printer);
843 papiServiceDestroy (service);
844 gtk_printer_set_has_details (printer, TRUE);
846 return G_SOURCE_REMOVE;
850 papi_printer_request_details (GtkPrinter *printer)
852 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, papi_display_printer_status, printer, papi_display_printer_status_done);
856 static GtkPrintCapabilities
857 papi_printer_get_capabilities (GtkPrinter *printer)
859 return GTK_PRINT_CAPABILITY_COPIES | GTK_PRINT_CAPABILITY_PAGE_SET ;