(root)/
glib-2.79.0/
gio/
gpowerprofilemonitordbus.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright 2019 Red Hat, Inc.
       4   * Copyrgith 2021 Igalia S.L.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   *
       8   * This library is free software; you can redistribute it and/or
       9   * modify it under the terms of the GNU Lesser General Public
      10   * License as published by the Free Software Foundation; either
      11   * version 2.1 of the License, or (at your option) any later version.
      12   *
      13   * This library is distributed in the hope that it will be useful,
      14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16   * Lesser General Public License for more details.
      17   *
      18   * You should have received a copy of the GNU Lesser General
      19   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include "gpowerprofilemonitor.h"
      25  #include "gpowerprofilemonitordbus.h"
      26  #include "gioerror.h"
      27  #include "ginitable.h"
      28  #include "giomodule-priv.h"
      29  #include "glibintl.h"
      30  #include "glib/gstdio.h"
      31  #include "gcancellable.h"
      32  #include "gdbusproxy.h"
      33  #include "gdbusnamewatching.h"
      34  
      35  #define G_POWER_PROFILE_MONITOR_DBUS_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable))
      36  
      37  static void g_power_profile_monitor_dbus_iface_init (GPowerProfileMonitorInterface *iface);
      38  static void g_power_profile_monitor_dbus_initable_iface_init (GInitableIface *iface);
      39  
      40  struct _GPowerProfileMonitorDBus
      41  {
      42    GObject parent_instance;
      43  
      44    guint watch_id;
      45    GCancellable *cancellable;
      46    GDBusProxy *proxy;
      47    gulong signal_id;
      48  
      49    gboolean power_saver_enabled;
      50  };
      51  
      52  typedef enum
      53  {
      54    PROP_POWER_SAVER_ENABLED = 1,
      55  } GPowerProfileMonitorDBusProperty;
      56  
      57  #define POWERPROFILES_DBUS_NAME "net.hadess.PowerProfiles"
      58  #define POWERPROFILES_DBUS_IFACE "net.hadess.PowerProfiles"
      59  #define POWERPROFILES_DBUS_PATH "/net/hadess/PowerProfiles"
      60  
      61  G_DEFINE_TYPE_WITH_CODE (GPowerProfileMonitorDBus, g_power_profile_monitor_dbus, G_TYPE_OBJECT,
      62                           G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
      63                                                  g_power_profile_monitor_dbus_initable_iface_init)
      64                           G_IMPLEMENT_INTERFACE (G_TYPE_POWER_PROFILE_MONITOR,
      65                                                  g_power_profile_monitor_dbus_iface_init)
      66                           _g_io_modules_ensure_extension_points_registered ();
      67                           g_io_extension_point_implement (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME,
      68                                                           g_define_type_id,
      69                                                           "dbus",
      70                                                           30))
      71  
      72  static void
      73  g_power_profile_monitor_dbus_init (GPowerProfileMonitorDBus *dbus)
      74  {
      75    dbus->power_saver_enabled = FALSE;
      76  }
      77  
      78  static void
      79  ppd_properties_changed_cb (GDBusProxy *proxy,
      80                             GVariant   *changed_properties,
      81                             GStrv      *invalidated_properties,
      82                             gpointer    user_data)
      83  {
      84    GPowerProfileMonitorDBus *dbus = user_data;
      85    const char *active_profile;
      86    gboolean enabled;
      87  
      88    if (!g_variant_lookup (changed_properties, "ActiveProfile", "&s", &active_profile))
      89      return;
      90  
      91    enabled = g_strcmp0 (active_profile, "power-saver") == 0;
      92    if (enabled == dbus->power_saver_enabled)
      93      return;
      94  
      95    dbus->power_saver_enabled = enabled;
      96    g_object_notify (G_OBJECT (dbus), "power-saver-enabled");
      97  }
      98  
      99  static void
     100  ppd_proxy_cb (GObject      *source_object,
     101                GAsyncResult *res,
     102                gpointer      user_data)
     103  {
     104    GPowerProfileMonitorDBus *dbus = user_data;
     105    GVariant *active_profile_variant;
     106    GDBusProxy *proxy;
     107    GError *error = NULL;
     108    const char *active_profile;
     109    gboolean power_saver_enabled;
     110  
     111    proxy = g_dbus_proxy_new_finish (res, &error);
     112    if (!proxy)
     113      {
     114        g_debug ("GPowerProfileMonitorDBus: Failed to create PowerProfiles D-Bus proxy: %s",
     115                 error->message);
     116        g_error_free (error);
     117        return;
     118      }
     119  
     120    active_profile_variant = g_dbus_proxy_get_cached_property (proxy, "ActiveProfile");
     121    if (active_profile_variant != NULL &&
     122        g_variant_is_of_type (active_profile_variant, G_VARIANT_TYPE_STRING))
     123      {
     124        active_profile = g_variant_get_string (active_profile_variant, NULL);
     125        power_saver_enabled = g_strcmp0 (active_profile, "power-saver") == 0;
     126        if (power_saver_enabled != dbus->power_saver_enabled)
     127          {
     128            dbus->power_saver_enabled = power_saver_enabled;
     129            g_object_notify (G_OBJECT (dbus), "power-saver-enabled");
     130          }
     131      }
     132    g_clear_pointer (&active_profile_variant, g_variant_unref);
     133  
     134    dbus->signal_id = g_signal_connect (G_OBJECT (proxy), "g-properties-changed",
     135                                        G_CALLBACK (ppd_properties_changed_cb), dbus);
     136    dbus->proxy = g_steal_pointer (&proxy);
     137  }
     138  
     139  static void
     140  ppd_appeared_cb (GDBusConnection *connection,
     141                   const gchar     *name,
     142                   const gchar     *name_owner,
     143                   gpointer         user_data)
     144  {
     145    GPowerProfileMonitorDBus *dbus = user_data;
     146  
     147    g_dbus_proxy_new (connection,
     148                      G_DBUS_PROXY_FLAGS_NONE,
     149                      NULL,
     150                      POWERPROFILES_DBUS_NAME,
     151                      POWERPROFILES_DBUS_PATH,
     152                      POWERPROFILES_DBUS_IFACE,
     153                      dbus->cancellable,
     154                      ppd_proxy_cb,
     155                      dbus);
     156  }
     157  
     158  static void
     159  ppd_vanished_cb (GDBusConnection *connection,
     160                   const gchar     *name,
     161                   gpointer         user_data)
     162  {
     163    GPowerProfileMonitorDBus *dbus = user_data;
     164  
     165    g_clear_signal_handler (&dbus->signal_id, dbus->proxy);
     166    g_clear_object (&dbus->proxy);
     167  
     168    dbus->power_saver_enabled = FALSE;
     169    g_object_notify (G_OBJECT (dbus), "power-saver-enabled");
     170  }
     171  
     172  static void
     173  g_power_profile_monitor_dbus_get_property (GObject    *object,
     174                                             guint       prop_id,
     175                                             GValue     *value,
     176                                             GParamSpec *pspec)
     177  {
     178    GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (object);
     179  
     180    switch ((GPowerProfileMonitorDBusProperty) prop_id)
     181      {
     182      case PROP_POWER_SAVER_ENABLED:
     183        g_value_set_boolean (value, dbus->power_saver_enabled);
     184        break;
     185  
     186      default:
     187        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     188      }
     189  }
     190  
     191  static gboolean
     192  g_power_profile_monitor_dbus_initable_init (GInitable     *initable,
     193                                              GCancellable  *cancellable,
     194                                              GError       **error)
     195  {
     196    GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (initable);
     197  
     198    dbus->cancellable = g_cancellable_new ();
     199    dbus->watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
     200                                       POWERPROFILES_DBUS_NAME,
     201                                       G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
     202                                       ppd_appeared_cb,
     203                                       ppd_vanished_cb,
     204                                       dbus,
     205                                       NULL);
     206  
     207    return TRUE;
     208  }
     209  
     210  static void
     211  g_power_profile_monitor_dbus_finalize (GObject *object)
     212  {
     213    GPowerProfileMonitorDBus *dbus = G_POWER_PROFILE_MONITOR_DBUS (object);
     214  
     215    g_cancellable_cancel (dbus->cancellable);
     216    g_clear_object (&dbus->cancellable);
     217    g_clear_signal_handler (&dbus->signal_id, dbus->proxy);
     218    g_clear_object (&dbus->proxy);
     219    g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name);
     220  
     221    G_OBJECT_CLASS (g_power_profile_monitor_dbus_parent_class)->finalize (object);
     222  }
     223  
     224  static void
     225  g_power_profile_monitor_dbus_class_init (GPowerProfileMonitorDBusClass *nl_class)
     226  {
     227    GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
     228  
     229    gobject_class->get_property = g_power_profile_monitor_dbus_get_property;
     230    gobject_class->finalize = g_power_profile_monitor_dbus_finalize;
     231  
     232    g_object_class_override_property (gobject_class, PROP_POWER_SAVER_ENABLED, "power-saver-enabled");
     233  }
     234  
     235  static void
     236  g_power_profile_monitor_dbus_iface_init (GPowerProfileMonitorInterface *monitor_iface)
     237  {
     238  }
     239  
     240  static void
     241  g_power_profile_monitor_dbus_initable_iface_init (GInitableIface *iface)
     242  {
     243    iface->init = g_power_profile_monitor_dbus_initable_init;
     244  }