/* * Copyright (C) 2016 Red Hat, Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: Martin Hatina * Marek Kasik */ #include "pp-printer.h" #include "pp-utils.h" typedef struct _PpPrinter PpPrinter; typedef struct _PpPrinterPrivate PpPrinterPrivate; struct _PpPrinter { GObject parent_instance; PpPrinterPrivate *priv; }; struct _PpPrinterPrivate { gchar *printer_name; }; G_DEFINE_TYPE_WITH_PRIVATE (PpPrinter, pp_printer, G_TYPE_OBJECT) enum { PROP_0 = 0, PROP_NAME }; static void pp_printer_dispose (GObject *object) { PpPrinterPrivate *priv = PP_PRINTER (object)->priv; g_free (priv->printer_name); G_OBJECT_CLASS (pp_printer_parent_class)->dispose (object); } static void pp_printer_finalize (GObject *object) { G_OBJECT_CLASS (pp_printer_parent_class)->finalize (object); } static void pp_printer_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PpPrinter *self = PP_PRINTER (object); switch (property_id) { case PROP_NAME: g_value_set_string (value, self->priv->printer_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pp_printer_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PpPrinter *self = PP_PRINTER (object); switch (property_id) { case PROP_NAME: g_free (self->priv->printer_name); self->priv->printer_name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pp_printer_class_init (PpPrinterClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = pp_printer_set_property; gobject_class->get_property = pp_printer_get_property; gobject_class->dispose = pp_printer_dispose; gobject_class->finalize = pp_printer_finalize; g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string ("printer-name", "Printer name", "Name of this printer", NULL, G_PARAM_READWRITE)); } static void pp_printer_init (PpPrinter *printer) { printer->priv = G_TYPE_INSTANCE_GET_PRIVATE (printer, PP_TYPE_PRINTER, PpPrinterPrivate); } PpPrinter * pp_printer_new (const gchar *name) { PpPrinter *self = g_object_new (PP_TYPE_PRINTER, "printer-name", name, NULL); return self; } static void printer_rename_thread (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { PpPrinter *printer = PP_PRINTER (source_object); gboolean result; gchar *new_printer_name = task_data; gchar *old_printer_name; g_object_get (printer, "printer-name", &old_printer_name, NULL); result = printer_rename (old_printer_name, new_printer_name); if (result) { g_object_set (printer, "printer-name", new_printer_name, NULL); } g_free (old_printer_name); g_task_return_boolean (task, result); } static void printer_rename_dbus_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { PpPrinter *printer; GVariant *output; gboolean result = FALSE; GError *error = NULL; GTask *task = user_data; gchar *old_printer_name; output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); g_object_unref (source_object); if (output != NULL) { const gchar *ret_error; printer = g_task_get_source_object (task); g_object_get (printer, "printer-name", &old_printer_name, NULL); g_variant_get (output, "(&s)", &ret_error); if (ret_error[0] != '\0') { g_warning ("cups-pk-helper: renaming of printer %s failed: %s", old_printer_name, ret_error); } else { result = TRUE; g_object_set (printer, "printer-name", g_task_get_task_data (task), NULL); } g_task_return_boolean (task, result); g_free (old_printer_name); g_variant_unref (output); } else { if (error->domain == G_DBUS_ERROR && (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN || error->code == G_DBUS_ERROR_UNKNOWN_METHOD)) { g_warning ("Update cups-pk-helper to at least 0.2.6 please to be able to use PrinterRename method."); g_error_free (error); g_task_run_in_thread (task, printer_rename_thread); } else { g_task_return_boolean (task, FALSE); } } } static void get_bus_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GDBusConnection *bus; GError *error = NULL; GTask *task = user_data; gchar *printer_name; bus = g_bus_get_finish (res, &error); if (bus != NULL) { g_object_get (g_task_get_source_object (task), "printer-name", &printer_name, NULL); g_dbus_connection_call (bus, MECHANISM_BUS, "/", MECHANISM_BUS, "PrinterRename", g_variant_new ("(ss)", printer_name, g_task_get_task_data (task)), G_VARIANT_TYPE ("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, g_task_get_cancellable (task), printer_rename_dbus_cb, task); g_free (printer_name); } else { g_warning ("Failed to get system bus: %s", error->message); g_error_free (error); g_task_return_boolean (task, FALSE); } } void pp_printer_rename_async (PpPrinter *printer, const gchar *new_printer_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; task = g_task_new (G_OBJECT (printer), cancellable, callback, user_data); g_task_set_task_data (task, g_strdup (new_printer_name), g_free); g_bus_get (G_BUS_TYPE_SYSTEM, cancellable, get_bus_cb, task); } gboolean pp_printer_rename_finish (PpPrinter *printer, GAsyncResult *res, GError **error) { g_return_val_if_fail (g_task_is_valid (res, printer), FALSE); g_object_unref (res); return g_task_propagate_boolean (G_TASK (res), error); }