📄 gtkprintbackendcups.c
字号:
g_free (job_uri); cups_request_execute (data->print_backend, request, (GtkPrintCupsResponseCallbackFunc) cups_request_job_info_cb, data, NULL);}static gbooleancups_job_info_poll_timeout (gpointer user_data){ CupsJobPollData *data = user_data; if (data->job == NULL) cups_job_poll_data_free (data); else cups_request_job_info (data); return FALSE;}static voidcups_begin_polling_info (GtkPrintBackendCups *print_backend, GtkPrintJob *job, gint job_id){ CupsJobPollData *data; data = g_new0 (CupsJobPollData, 1); data->print_backend = print_backend; data->job = job; data->job_id = job_id; data->counter = 0; g_object_weak_ref (G_OBJECT (job), job_object_died, data); cups_request_job_info (data);}static voidmark_printer_inactive (GtkPrinter *printer, GtkPrintBackend *backend){ gtk_printer_set_is_active (printer, FALSE); g_signal_emit_by_name (backend, "printer-removed", printer);}static gintfind_printer (GtkPrinter *printer, const gchar *find_name){ const gchar *printer_name; printer_name = gtk_printer_get_name (printer); return g_ascii_strcasecmp (printer_name, find_name);}static voidcups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, GtkCupsResult *result, gpointer user_data){ GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend); ipp_attribute_t *attr; ipp_t *response; gboolean list_has_changed; GList *removed_printer_checklist; GDK_THREADS_ENTER (); 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)) { GTK_NOTE (PRINTING, g_warning ("CUPS Backend: Error getting printer list: %s", gtk_cups_result_get_error_string (result))); goto done; } /* Gather the names of the printers in the current queue * so we may check to see if they were removed */ removed_printer_checklist = gtk_print_backend_get_printer_list (backend); response = gtk_cups_result_get_response (result); for (attr = response->attrs; attr != NULL; attr = attr->next) { GtkPrinter *printer; const gchar *printer_name = NULL; const gchar *printer_uri = NULL; const gchar *member_uris = NULL; const gchar *location = NULL; const gchar *description = NULL; const gchar *state_msg = NULL; gint state = 0; gint job_count = 0; gboolean status_changed = FALSE; GList *node; /* Skip leading attributes until we hit a printer... */ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) attr = attr->next; if (attr == NULL) break; while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { if (strcmp (attr->name, "printer-name") == 0 && attr->value_tag == IPP_TAG_NAME) printer_name = attr->values[0].string.text; else if (strcmp (attr->name, "printer-uri-supported") == 0 && attr->value_tag == IPP_TAG_URI) printer_uri = attr->values[0].string.text; else if (strcmp (attr->name, "member-uris") == 0 && attr->value_tag == IPP_TAG_URI) member_uris = attr->values[0].string.text; else if (strcmp (attr->name, "printer-location") == 0) location = attr->values[0].string.text; else if (strcmp (attr->name, "printer-info") == 0) description = attr->values[0].string.text; else if (strcmp (attr->name, "printer-state-message") == 0) state_msg = attr->values[0].string.text; else if (strcmp (attr->name, "printer-state") == 0) state = attr->values[0].integer; else if (strcmp (attr->name, "queued-job-count") == 0) job_count = attr->values[0].integer; else { GTK_NOTE (PRINTING, g_print ("CUPS Backend: Attribute %s ignored", attr->name)); } attr = attr->next; } if (printer_name == NULL || (printer_uri == NULL && member_uris == NULL)) { if (attr == NULL) break; else continue; } /* remove name from checklist if it was found */ node = g_list_find_custom (removed_printer_checklist, printer_name, (GCompareFunc) find_printer); removed_printer_checklist = g_list_delete_link (removed_printer_checklist, node); printer = gtk_print_backend_find_printer (backend, printer_name); if (!printer) { GtkPrinterCups *cups_printer; char uri[HTTP_MAX_URI]; /* Printer URI */ char method[HTTP_MAX_URI]; /* Method/scheme name */ char username[HTTP_MAX_URI]; /* Username:password */ char hostname[HTTP_MAX_URI]; /* Hostname */ char resource[HTTP_MAX_URI]; /* Resource name */ int port; /* Port number */ list_has_changed = TRUE; cups_printer = gtk_printer_cups_new (printer_name, backend); 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); /* 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); 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, method, sizeof (method), username, sizeof (username), hostname, sizeof (hostname), &port, resource, sizeof (resource));#else httpSeparate (cups_printer->printer_uri, method, username, hostname, &port, resource);#endif if (strncmp (resource, "/printers/", 10) == 0) { 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"); cups_printer->hostname = g_strdup (hostname); cups_printer->port = port; printer = GTK_PRINTER (cups_printer); if (cups_backend->default_printer != NULL && strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0) gtk_printer_set_is_default (printer, TRUE); gtk_print_backend_add_printer (backend, printer); } else g_object_ref (printer); if (!gtk_printer_is_active (printer)) { gtk_printer_set_is_active (printer, TRUE); gtk_printer_set_is_new (printer, TRUE); list_has_changed = TRUE; } if (gtk_printer_is_new (printer)) { g_signal_emit_by_name (backend, "printer-added", printer); gtk_printer_set_is_new (printer, FALSE); }#if 0 /* Getting printer info with separate requests overwhelms cups * when the printer list has more than a handful of printers. */ cups_request_printer_info (cups_backend, gtk_printer_get_name (printer));#endif GTK_PRINTER_CUPS (printer)->state = state; status_changed = gtk_printer_set_job_count (printer, job_count); status_changed |= gtk_printer_set_location (printer, location); status_changed |= gtk_printer_set_description (printer, description); status_changed |= gtk_printer_set_state_message (printer, state_msg); if (status_changed) g_signal_emit_by_name (GTK_PRINT_BACKEND (backend), "printer-status-changed", printer); /* The ref is held by GtkPrintBackend, in add_printer() */ g_object_unref (printer); if (attr == NULL) break; } /* look at the removed printers checklist and mark any printer as inactive if it is in the list, emitting a printer_removed signal */ if (removed_printer_checklist != NULL) { g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, backend); g_list_free (removed_printer_checklist); list_has_changed = TRUE; } done: if (list_has_changed) g_signal_emit_by_name (backend, "printer-list-changed"); gtk_print_backend_set_list_done (backend); GDK_THREADS_LEAVE ();}static gbooleancups_request_printer_list (GtkPrintBackendCups *cups_backend){ GtkCupsRequest *request; static const char * const pattrs[] = /* Attributes we're interested in */ { "printer-name", "printer-uri-supported", "member-uris", "printer-location", "printer-info", "printer-state-message", "printer-state", "queued-job-count" }; if (cups_backend->list_printers_pending || !cups_backend->got_default_printer) return TRUE; cups_backend->list_printers_pending = TRUE; request = gtk_cups_request_new (NULL, GTK_CUPS_POST, CUPS_GET_PRINTERS, NULL, NULL, NULL); gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", G_N_ELEMENTS (pattrs), NULL, pattrs); cups_request_execute (cups_backend, request, (GtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb, request, NULL); return TRUE;}static voidcups_get_printer_list (GtkPrintBackend *backend){ GtkPrintBackendCups *cups_backend; cups_backend = GTK_PRINT_BACKEND_CUPS (backend); if (cups_backend->list_printers_poll == 0) { cups_request_printer_list (cups_backend); cups_backend->list_printers_poll = gdk_threads_add_timeout (3000, (GSourceFunc) cups_request_printer_list, backend); }}typedef struct { GtkPrinterCups *printer; GIOChannel *ppd_io; http_t *http;} GetPPDData;static voidget_ppd_data_free (GetPPDData *data){ GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); httpClose (data->http); g_io_channel_unref (data->ppd_io); g_object_unref (data->printer); g_free (data);}static voidcups_request_ppd_cb (GtkPrintBackendCups *print_backend, GtkCupsResult *result, GetPPDData *data){ ipp_t *response; GtkPrinter *printer; GDK_THREADS_ENTER (); 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)) { gboolean success = FALSE; /* if we get a 404 then it is just a raw printer without a ppd and not an error */ if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) && (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND)) { gtk_printer_set_has_details (printer, TRUE); success = TRUE; } g_signal_emit_by_name (printer, "details-acquired", success); goto done; } response = gtk_cups_result_get_response (result); /* 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", TRUE);done: GDK_THREADS_LEAVE ();}static voidcups_request_ppd (GtkPrinter *printer){ GError *error; 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)); http = httpConnectEncrypt (cups_printer->hostname, cups_printer->port, cupsEncryption ()); data = g_new0 (GetPPDData, 1); 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) { GTK_NOTE (PRINTING, g_warning ("CUPS Backend: Failed to create temp file, %s\n", error->message)); g_error_free (error);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -