#include "gtkprintercups.h"
#include "gtkcupsutils.h"
+#include "gtkdebug.h"
typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
GtkPrinterOptionSet *options);
static GtkPrinterOptionSet *cups_printer_get_options (GtkPrinter *printer,
GtkPrintSettings *settings,
- GtkPageSetup *page_setup);
+ GtkPageSetup *page_setup,
+ GtkPrintCapabilities capabilities);
static void cups_printer_prepare_for_print (GtkPrinter *printer,
GtkPrintJob *print_job,
GtkPrintSettings *settings,
static gboolean cups_job_info_poll_timeout (gpointer user_data);
static void gtk_print_backend_cups_print_stream (GtkPrintBackend *backend,
GtkPrintJob *job,
- gint data_fd,
+ GIOChannel *data_io,
GtkPrintJobCompleteFunc callback,
gpointer user_data,
GDestroyNotify dnotify);
GtkPrintSettings *settings,
gdouble width,
gdouble height,
- gint cache_fd);
+ GIOChannel *cache_io);
static void
G_MODULE_EXPORT void
pb_module_init (GTypeModule *module)
{
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Initializing the CUPS print backend module\n"));
+
gtk_print_backend_cups_register_type (module);
gtk_printer_cups_register_type (module);
}
GtkPrintBackend *
gtk_print_backend_cups_new (void)
{
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Creating a new CUPS print backend object\n"));
+
return g_object_new (GTK_TYPE_PRINT_BACKEND_CUPS, NULL);
}
const unsigned char *data,
unsigned int length)
{
- gint fd = GPOINTER_TO_INT (closure);
- gssize written;
-
+ GIOChannel *io = (GIOChannel *)closure;
+ gsize written;
+ GError *error;
+
+ error = NULL;
+
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Writting %i byte chunk to temp file\n", length));
+
while (length > 0)
{
- written = write (fd, data, length);
+ g_io_channel_write_chars (io, data, length, &written, &error);
- if (written == -1)
+ if (error != NULL)
{
- if (errno == EAGAIN || errno == EINTR)
- continue;
-
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Error writting to temp file, %s\n", error->message));
+
+ g_error_free (error);
return CAIRO_STATUS_WRITE_ERROR;
}
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Wrote %i bytes to temp file\n", written));
+
data += written;
length -= written;
}
GtkPrintSettings *settings,
gdouble width,
gdouble height,
- gint cache_fd)
+ GIOChannel *cache_io)
{
cairo_surface_t *surface;
/* TODO: check if it is a ps or pdf printer */
- surface = cairo_ps_surface_create_for_stream (_cairo_write_to_cups, GINT_TO_POINTER (cache_fd), width, height);
+ surface = cairo_ps_surface_create_for_stream (_cairo_write_to_cups, cache_io, width, height);
/* TODO: DPI from settings object? */
cairo_surface_set_fallback_resolution (surface, 300, 300);
static void
cups_free_print_stream_data (CupsPrintStreamData *data)
{
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
if (data->dnotify)
data->dnotify (data->user_data);
g_object_unref (data->job);
GError *error = NULL;
CupsPrintStreamData *ps = user_data;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
if (gtk_cups_result_is_error (result))
error = g_error_new_literal (gtk_print_error_quark (),
GTK_PRINT_ERROR_INTERNAL_ERROR,
static void
gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
GtkPrintJob *job,
- gint data_fd,
+ GIOChannel *data_io,
GtkPrintJobCompleteFunc callback,
gpointer user_data,
GDestroyNotify dnotify)
GtkPrintSettings *settings;
const gchar *title;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
settings = gtk_print_job_get_settings (job);
request = gtk_cups_request_new (NULL,
GTK_CUPS_POST,
IPP_PRINT_JOB,
- data_fd,
+ data_io,
NULL,
cups_printer->device_uri);
static void
gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
{
- backend_cups->list_printers_poll = 0;
+ backend_cups->list_printers_poll = FALSE;
+ backend_cups->got_default_printer = FALSE;
backend_cups->list_printers_pending = FALSE;
cups_request_default_printer (backend_cups);
gtk_print_backend_cups_finalize (GObject *object)
{
GtkPrintBackendCups *backend_cups;
+
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: finalizing CUPS backend module\n"));
backend_cups = GTK_PRINT_BACKEND_CUPS (object);
{
GtkPrintBackendCups *backend_cups;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
backend_cups = GTK_PRINT_BACKEND_CUPS (object);
if (backend_cups->list_printers_poll > 0)
GtkCupsPollState poll_state;
gboolean result;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
dispatch = (GtkPrintCupsDispatchWatch *) source;
poll_state = gtk_cups_request_get_poll_state (dispatch->request);
GtkPrintCupsDispatchWatch *dispatch;
dispatch = (GtkPrintCupsDispatchWatch *) source;
-
+
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
*timeout_ = -1;
return gtk_cups_request_read_write (dispatch->request);
result = gtk_cups_request_get_result (dispatch->request);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
if (gtk_cups_result_is_error (result))
- g_warning (gtk_cups_result_get_error_string (result));
+ g_warning ("Error result: %s", gtk_cups_result_get_error_string (result));
ep_callback (GTK_PRINT_BACKEND (dispatch->backend), result, user_data);
{
GtkPrintCupsDispatchWatch *dispatch;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
dispatch = (GtkPrintCupsDispatchWatch *) source;
gtk_cups_request_free (dispatch->request);
dispatch = (GtkPrintCupsDispatchWatch *) g_source_new (&_cups_dispatch_watch_funcs,
sizeof (GtkPrintCupsDispatchWatch));
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s'\n", G_STRFUNC, dispatch, request->server, request->resource));
+
dispatch->request = request;
dispatch->backend = g_object_ref (print_backend);
dispatch->data_poll = NULL;
printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (backend),
printer_name);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s - Got printer info for printer '%s'\n", G_STRFUNC, printer_name));
+
if (!printer)
- return;
+ {
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Could not find printer called '%s'\n", printer_name));
+ return;
+ }
cups_printer = GTK_PRINTER_CUPS (printer);
request = gtk_cups_request_new (NULL,
GTK_CUPS_POST,
IPP_GET_PRINTER_ATTRIBUTES,
- 0,
+ NULL,
NULL,
NULL);
gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s - Requesting printer info for URI '%s'\n", G_STRFUNC, printer_uri));
+
g_free (printer_uri);
gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
request = gtk_cups_request_new (NULL,
GTK_CUPS_POST,
IPP_GET_JOB_ATTRIBUTES,
- 0,
+ NULL,
NULL,
NULL);
list_has_changed = FALSE;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
cups_backend->list_printers_pending = FALSE;
if (gtk_cups_result_is_error (result))
{
g_warning ("Error getting printer list: %s", gtk_cups_result_get_error_string (result));
- return;
+
+ goto done;
}
/* Gather the names of the printers in the current queue
else if (!strcmp (attr->name, "member-uris") &&
attr->value_tag == IPP_TAG_URI)
member_uris = attr->values[0].string.text;
+ else
+ {
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Attribute %s ignored", attr->name));
+ }
attr = attr->next;
}
cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
+ /* Check to see if we are looking at a class */
if (member_uris)
- cups_printer->printer_uri = g_strdup (member_uris);
+ {
+ cups_printer->printer_uri = g_strdup (member_uris);
+ /* TODO if member_uris is a class we need to recursivly find a printer */
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Found class with printer %s\n", member_uris));
+ }
else
- cups_printer->printer_uri = g_strdup (printer_uri);
+ {
+ cups_printer->printer_uri = g_strdup (printer_uri);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Found printer %s\n", printer_uri));
+ }
#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri,
resource);
#endif
+ if (!strncmp (resource, "/printers/", 10))
+ {
+ cups_printer->ppd_name = g_strdup (resource + 10);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n", cups_printer->ppd_name, printer_name));
+ }
+
gethostname (uri, sizeof(uri));
if (strcasecmp (uri, hostname) == 0)
strcpy (hostname, "localhost");
list_has_changed = TRUE;
}
+done:
if (list_has_changed)
g_signal_emit_by_name (backend, "printer-list-changed");
!cups_backend->got_default_printer)
return TRUE;
+ g_object_ref (cups_backend);
+ GDK_THREADS_LEAVE ();
+
cups_backend->list_printers_pending = TRUE;
request = gtk_cups_request_new (NULL,
GTK_CUPS_POST,
CUPS_GET_PRINTERS,
- 0,
+ NULL,
NULL,
NULL);
(GtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb,
request,
NULL);
+ GDK_THREADS_ENTER ();
+ g_object_unref (cups_backend);
return TRUE;
}
if (cups_backend->list_printers_poll == 0)
{
cups_request_printer_list (cups_backend);
- cups_backend->list_printers_poll = g_timeout_add (3000 * 100000,
+ cups_backend->list_printers_poll = gdk_threads_add_timeout (3000,
(GSourceFunc) cups_request_printer_list,
backend);
}
typedef struct {
GtkPrinterCups *printer;
- gint ppd_fd;
- gchar *ppd_filename;
+ GIOChannel *ppd_io;
} GetPPDData;
static void
get_ppd_data_free (GetPPDData *data)
{
- close (data->ppd_fd);
- unlink (data->ppd_filename);
- g_free (data->ppd_filename);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
+ g_io_channel_unref (data->ppd_io);
g_object_unref (data->printer);
g_free (data);
}
ipp_t *response;
GtkPrinter *printer;
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
printer = GTK_PRINTER (data->printer);
GTK_PRINTER_CUPS (printer)->reading_ppd = FALSE;
if (gtk_cups_result_is_error (result))
{
- g_signal_emit_by_name (printer, "details-acquired", printer, FALSE);
+ g_signal_emit_by_name (printer, "details-acquired", FALSE);
return;
}
response = gtk_cups_result_get_response (result);
- data->printer->ppd_file = ppdOpenFile (data->ppd_filename);
+ /* let ppdOpenFd take over the ownership of the open file */
+ g_io_channel_seek_position (data->ppd_io, 0, G_SEEK_SET, NULL);
+ data->printer->ppd_file = ppdOpenFd (dup (g_io_channel_unix_get_fd (data->ppd_io)));
+
gtk_printer_set_has_details (printer, TRUE);
- g_signal_emit_by_name (printer, "details-acquired", printer, TRUE);
+ g_signal_emit_by_name (printer, "details-acquired", TRUE);
}
static void
GtkPrintBackend *print_backend;
GtkPrinterCups *cups_printer;
GtkCupsRequest *request;
+ char *ppd_filename;
gchar *resource;
http_t *http;
GetPPDData *data;
-
+ int fd;
+
cups_printer = GTK_PRINTER_CUPS (printer);
error = NULL;
+
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
/* FIXME this can return NULL! */
http = httpConnectEncrypt (cups_printer->hostname,
cups_printer->port,
data = g_new0 (GetPPDData, 1);
- data->ppd_fd = g_file_open_tmp ("gtkprint_ppd_XXXXXX",
- &data->ppd_filename,
- &error);
+ fd = g_file_open_tmp ("gtkprint_ppd_XXXXXX",
+ &ppd_filename,
+ &error);
+
+#ifdef G_ENABLE_DEBUG
+ /* If we are debugging printing don't delete the tmp files */
+ if (!(gtk_debug_flags & GTK_DEBUG_PRINTING))
+ unlink (ppd_filename);
+#else
+ unlink (ppd_filename);
+#endif /* G_ENABLE_DEBUG */
if (error != NULL)
{
g_warning ("%s", error->message);
g_error_free (error);
httpClose (http);
+ g_free (ppd_filename);
g_free (data);
- g_signal_emit_by_name (printer, "details-acquired", printer, FALSE);
+ g_signal_emit_by_name (printer, "details-acquired", FALSE);
return;
}
- fchmod (data->ppd_fd, S_IRUSR | S_IWUSR);
+ fchmod (fd, S_IRUSR | S_IWUSR);
+ data->ppd_io = g_io_channel_unix_new (fd);
+ g_io_channel_set_encoding (data->ppd_io, NULL, NULL);
+ g_io_channel_set_close_on_unref (data->ppd_io, TRUE);
data->printer = g_object_ref (printer);
- resource = g_strdup_printf ("/printers/%s.ppd", gtk_printer_get_name (printer));
+ resource = g_strdup_printf ("/printers/%s.ppd",
+ gtk_printer_cups_get_ppd_name (GTK_PRINTER_CUPS(printer)));
request = gtk_cups_request_new (http,
GTK_CUPS_GET,
0,
- data->ppd_fd,
+ data->ppd_io,
cups_printer->hostname,
resource);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n", resource, ppd_filename));
+
g_free (resource);
-
+ g_free (ppd_filename);
+
cups_printer->reading_ppd = TRUE;
print_backend = gtk_printer_get_backend (printer);
request = gtk_cups_request_new (NULL,
GTK_CUPS_POST,
CUPS_GET_DEFAULT,
- 0,
+ NULL,
NULL,
NULL);
strcasecmp (value, "False") == 0);
}
+static char *
+ppd_group_name (ppd_group_t *group)
+{
+#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR > 1) || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR == 1 && CUPS_VERSION_PATCH >= 18)
+ return group->name;
+#else
+ return group->text;
+#endif
+}
+
static int
available_choices (ppd_file_t *ppd,
ppd_option_t *option,
installed_options = NULL;
for (i = 0; i < ppd->num_groups; i++)
{
- if (strcmp (ppd->groups[i].name, "InstallableOptions") == 0)
+ char *name;
+
+ name = ppd_group_name (&ppd->groups[i]);
+ if (strcmp (name, "InstallableOptions") == 0)
{
installed_options = &ppd->groups[i];
break;
char *label;
int n_choices;
int i;
+#ifdef HAVE_CUPS_API_1_2
+ ppd_coption_t *coption;
+#endif
g_assert (ppd_option->ui == PPD_UI_PICKONE);
n_choices = available_choices (ppd_file, ppd_option, &available, g_str_has_prefix (gtk_name, "gtk-"));
if (n_choices > 0)
{
+
+ /* right now only support one parameter per custom option
+ * if more than one print warning and only offer the default choices
+ */
+
label = get_option_text (ppd_file, ppd_option);
- option = gtk_printer_option_new (gtk_name, label,
- GTK_PRINTER_OPTION_TYPE_PICKONE);
+
+#ifdef HAVE_CUPS_API_1_2
+ coption = ppdFindCustomOption (ppd_file, ppd_option->keyword);
+
+ if (coption)
+ {
+ ppd_cparam_t *cparam;
+
+ cparam = ppdFirstCustomParam (coption);
+
+ if (ppdNextCustomParam (coption) == NULL)
+ {
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_INT:
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_INT);
+ break;
+ case PPD_CUSTOM_PASSCODE:
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE);
+ break;
+ case PPD_CUSTOM_PASSWORD:
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD);
+ break;
+ case PPD_CUSTOM_REAL:
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_REAL);
+ break;
+ case PPD_CUSTOM_STRING:
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_STRING);
+ break;
+ case PPD_CUSTOM_POINTS:
+ g_warning ("Not Supported: PPD Custom Points Option");
+ break;
+ case PPD_CUSTOM_CURVE:
+ g_warning ("Not Supported: PPD Custom Curve Option");
+ break;
+ case PPD_CUSTOM_INVCURVE:
+ g_warning ("Not Supported: PPD Custom Inverse Curve Option");
+ break;
+ }
+ }
+ else
+ g_warning ("Not Supported: PPD Custom Option has more than one parameter");
+ }
+#endif /* HAVE_CUPS_API_1_2 */
+
+ if (!option)
+ option = gtk_printer_option_new (gtk_name, label,
+ GTK_PRINTER_OPTION_TYPE_PICKONE);
g_free (label);
gtk_printer_option_allocate_choices (option, n_choices);
if (STRING_IN_TABLE (ppd_option->keyword, cups_option_blacklist))
return;
-
+
name = get_option_name (ppd_option->keyword);
option = NULL;
if (option)
{
- if (STRING_IN_TABLE (toplevel_group->name,
+ char *name;
+
+ name = ppd_group_name (toplevel_group);
+ if (STRING_IN_TABLE (name,
color_group_whitelist) ||
STRING_IN_TABLE (ppd_option->keyword,
color_option_whitelist))
{
option->group = g_strdup ("ColorPage");
}
- else if (STRING_IN_TABLE (toplevel_group->name,
+ else if (STRING_IN_TABLE (name,
image_quality_group_whitelist) ||
STRING_IN_TABLE (ppd_option->keyword,
image_quality_option_whitelist))
{
option->group = g_strdup ("ImageQualityPage");
}
- else if (STRING_IN_TABLE (toplevel_group->name,
+ else if (STRING_IN_TABLE (name,
finishing_group_whitelist) ||
STRING_IN_TABLE (ppd_option->keyword,
finishing_option_whitelist))
GtkPrintSettings *settings)
{
gint i;
-
+ gchar *name;
+
/* Ignore installable options */
- if (strcmp (toplevel_group->name, "InstallableOptions") == 0)
+ name = ppd_group_name (toplevel_group);
+ if (strcmp (name, "InstallableOptions") == 0)
return;
for (i = 0; i < group->num_options; i++)
}
static GtkPrinterOptionSet *
-cups_printer_get_options (GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup)
+cups_printer_get_options (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup,
+ GtkPrintCapabilities capabilities)
{
GtkPrinterOptionSet *set;
GtkPrinterOption *option;
{
GtkPaperSize *paper_size;
ppd_option_t *option;
-
+ const gchar *ppd_name;
+
ppdMarkDefaults (ppd_file);
paper_size = gtk_page_setup_get_paper_size (page_setup);
option = ppdFindOption (ppd_file, "PageSize");
- strncpy (option->defchoice, gtk_paper_size_get_ppd_name (paper_size),
- PPD_MAX_NAME);
+ ppd_name = gtk_paper_size_get_ppd_name (paper_size);
+
+ if (ppd_name)
+ strncpy (option->defchoice, ppd_name, PPD_MAX_NAME);
+ else
+ {
+ gchar *custom_name;
+
+ custom_name = g_strdup_printf (_("Custom.%2fx%.2f"),
+ gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS),
+ gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS));
+ strncpy (option->defchoice, custom_name, PPD_MAX_NAME);
+ g_free (custom_name);
+ }
for (i = 0; i < ppd_file->num_groups; i++)
handle_group (set, ppd_file, &ppd_file->groups[i], &ppd_file->groups[i], settings);
}
static gboolean
-cups_printer_mark_conflicts (GtkPrinter *printer,
- GtkPrinterOptionSet *options)
+cups_printer_mark_conflicts (GtkPrinter *printer,
+ GtkPrinterOptionSet *options)
{
ppd_file_t *ppd_file;
int num_conflicts;