📄 gtkprintbackendcups.c
字号:
static voidgtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups){ backend_cups->list_printers_poll = FALSE; backend_cups->got_default_printer = FALSE; backend_cups->list_printers_pending = FALSE; cups_request_default_printer (backend_cups);}static voidgtk_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); g_free (backend_cups->default_printer); backend_cups->default_printer = NULL; backend_parent_class->finalize (object);}static voidgtk_print_backend_cups_dispose (GObject *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) g_source_remove (backend_cups->list_printers_poll); backend_cups->list_printers_poll = 0; backend_parent_class->dispose (object);}static gbooleancups_dispatch_watch_check (GSource *source){ GtkPrintCupsDispatchWatch *dispatch; 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); if (dispatch->request->http != NULL) { if (dispatch->data_poll == NULL) { dispatch->data_poll = g_new0 (GPollFD, 1); g_source_add_poll (source, dispatch->data_poll); } else { if (poll_state == GTK_CUPS_HTTP_READ) dispatch->data_poll->events = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI; else if (poll_state == GTK_CUPS_HTTP_WRITE) dispatch->data_poll->events = G_IO_OUT | G_IO_ERR; else dispatch->data_poll->events = 0; }#ifdef HAVE_CUPS_API_1_2 dispatch->data_poll->fd = httpGetFd (dispatch->request->http);#else dispatch->data_poll->fd = dispatch->request->http->fd;#endif } if (poll_state != GTK_CUPS_HTTP_IDLE) if (!(dispatch->data_poll->revents & dispatch->data_poll->events)) return FALSE; result = gtk_cups_request_read_write (dispatch->request); if (result && dispatch->data_poll != NULL) { g_source_remove_poll (source, dispatch->data_poll); g_free (dispatch->data_poll); dispatch->data_poll = NULL; } return result;}static gbooleancups_dispatch_watch_prepare (GSource *source, gint *timeout_){ 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);}static gbooleancups_dispatch_watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data){ GtkPrintCupsDispatchWatch *dispatch; GtkPrintCupsResponseCallbackFunc ep_callback; GtkCupsResult *result; g_assert (callback != NULL); ep_callback = (GtkPrintCupsResponseCallbackFunc) callback; dispatch = (GtkPrintCupsDispatchWatch *) source; 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)) { GTK_NOTE (PRINTING, g_print("Error result: %s (type %i, status %i, code %i)\n", gtk_cups_result_get_error_string (result), gtk_cups_result_get_error_type (result), gtk_cups_result_get_error_status (result), gtk_cups_result_get_error_code (result))); } ep_callback (GTK_PRINT_BACKEND (dispatch->backend), result, user_data); return FALSE;}static voidcups_dispatch_watch_finalize (GSource *source){ 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); if (dispatch->backend) { /* We need to unref this at idle time, because it might be the * last reference to this module causing the code to be * unloaded (including this particular function!) * Update: Doing this at idle caused a deadlock taking the * mainloop context lock while being in a GSource callout for * multithreaded apps. So, for now we just disable unloading * of print backends. See _gtk_print_backend_create for the * disabling. */ g_object_unref (dispatch->backend); dispatch->backend = NULL; } g_free (dispatch->data_poll);}static GSourceFuncs _cups_dispatch_watch_funcs = { cups_dispatch_watch_prepare, cups_dispatch_watch_check, cups_dispatch_watch_dispatch, cups_dispatch_watch_finalize};static voidcups_request_execute (GtkPrintBackendCups *print_backend, GtkCupsRequest *request, GtkPrintCupsResponseCallbackFunc callback, gpointer user_data, GDestroyNotify notify){ GtkPrintCupsDispatchWatch *dispatch; 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; g_source_set_callback ((GSource *) dispatch, (GSourceFunc) callback, user_data, notify); g_source_attach ((GSource *) dispatch, NULL); g_source_unref ((GSource *) dispatch);}#if 0static voidcups_request_printer_info_cb (GtkPrintBackendCups *backend, GtkCupsResult *result, gpointer user_data){ ipp_attribute_t *attr; ipp_t *response; gchar *printer_name; GtkPrinterCups *cups_printer; GtkPrinter *printer; gchar *loc; gchar *desc; gchar *state_msg; int job_count; gboolean status_changed; g_assert (GTK_IS_PRINT_BACKEND_CUPS (backend)); printer_name = (gchar *)user_data; 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) { GTK_NOTE (PRINTING, g_print ("CUPS Backend: Could not find printer called '%s'\n", printer_name)); return; } cups_printer = GTK_PRINTER_CUPS (printer); if (gtk_cups_result_is_error (result)) { if (gtk_printer_is_new (printer)) { gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend), printer); return; } else return; /* TODO: mark as inactive printer */ } response = gtk_cups_result_get_response (result); /* TODO: determine printer type and use correct icon */ gtk_printer_set_icon_name (printer, "gtk-print"); state_msg = ""; loc = ""; desc = ""; job_count = 0; for (attr = response->attrs; attr != NULL; attr = attr->next) { if (!attr->name) continue; _CUPS_MAP_ATTR_STR (attr, loc, "printer-location"); _CUPS_MAP_ATTR_STR (attr, desc, "printer-info"); _CUPS_MAP_ATTR_STR (attr, state_msg, "printer-state-message"); _CUPS_MAP_ATTR_INT (attr, cups_printer->state, "printer-state"); _CUPS_MAP_ATTR_INT (attr, job_count, "queued-job-count"); } status_changed = gtk_printer_set_job_count (printer, job_count); status_changed |= gtk_printer_set_location (printer, loc); status_changed |= gtk_printer_set_description (printer, desc); 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); }static voidcups_request_printer_info (GtkPrintBackendCups *print_backend, const gchar *printer_name){ GtkCupsRequest *request; gchar *printer_uri; static const char * const pattrs[] = /* Attributes we're interested in */ { "printer-location", "printer-info", "printer-state-message", "printer-state", "queued-job-count" }; request = gtk_cups_request_new (NULL, GTK_CUPS_POST, IPP_GET_PRINTER_ATTRIBUTES, NULL, NULL, NULL); printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", printer_name); 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, "requested-attributes", G_N_ELEMENTS (pattrs), NULL, pattrs); cups_request_execute (print_backend, request, (GtkPrintCupsResponseCallbackFunc) cups_request_printer_info_cb, g_strdup (printer_name), (GDestroyNotify) g_free);}#endiftypedef struct { GtkPrintBackendCups *print_backend; GtkPrintJob *job; int job_id; int counter;} CupsJobPollData;static voidjob_object_died (gpointer user_data, GObject *where_the_object_was){ CupsJobPollData *data = user_data; data->job = NULL;}static voidcups_job_poll_data_free (CupsJobPollData *data){ if (data->job) g_object_weak_unref (G_OBJECT (data->job), job_object_died, data); g_free (data);}static voidcups_request_job_info_cb (GtkPrintBackendCups *print_backend, GtkCupsResult *result, gpointer user_data){ CupsJobPollData *data = user_data; ipp_attribute_t *attr; ipp_t *response; int state; gboolean done; GDK_THREADS_ENTER (); if (data->job == NULL) { cups_job_poll_data_free (data); goto done; } data->counter++; response = gtk_cups_result_get_response (result); state = 0; for (attr = response->attrs; attr != NULL; attr = attr->next) { if (!attr->name) continue; _CUPS_MAP_ATTR_INT (attr, state, "job-state"); } done = FALSE; switch (state) { case IPP_JOB_PENDING: case IPP_JOB_HELD: case IPP_JOB_STOPPED: gtk_print_job_set_status (data->job, GTK_PRINT_STATUS_PENDING); break; case IPP_JOB_PROCESSING: gtk_print_job_set_status (data->job, GTK_PRINT_STATUS_PRINTING); break; default: case IPP_JOB_CANCELLED: case IPP_JOB_ABORTED: gtk_print_job_set_status (data->job, GTK_PRINT_STATUS_FINISHED_ABORTED); done = TRUE; break; case 0: case IPP_JOB_COMPLETED: gtk_print_job_set_status (data->job, GTK_PRINT_STATUS_FINISHED); done = TRUE; break; } if (!done && data->job != NULL) { guint32 timeout; if (data->counter < 5) timeout = 100; else if (data->counter < 10) timeout = 500; else timeout = 1000; g_timeout_add (timeout, cups_job_info_poll_timeout, data); } else cups_job_poll_data_free (data); done: GDK_THREADS_LEAVE ();}static voidcups_request_job_info (CupsJobPollData *data){ GtkCupsRequest *request; gchar *job_uri; request = gtk_cups_request_new (NULL, GTK_CUPS_POST, IPP_GET_JOB_ATTRIBUTES, NULL, NULL, NULL); job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", data->job_id); gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, job_uri);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -