From d67d887b61820ea78cd342d553eea866deae4502 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:03:23 -0500 Subject: add UPower xml files for gdbus-codegen --- src/org.freedesktop.UPower.Device.xml | 705 ++++++++++++++++++++++++++++++++++ src/org.freedesktop.UPower.xml | 43 +++ 2 files changed, 748 insertions(+) create mode 100644 src/org.freedesktop.UPower.Device.xml create mode 100644 src/org.freedesktop.UPower.xml diff --git a/src/org.freedesktop.UPower.Device.xml b/src/org.freedesktop.UPower.Device.xml new file mode 100644 index 0000000..7c9a65b --- /dev/null +++ b/src/org.freedesktop.UPower.Device.xml @@ -0,0 +1,705 @@ + +]> + + + + + + Objects implementing this interface are usually discovered through + the org.freedesktop.UPower interface on + the /org/freedesktop/UPower object on + the D-Bus system bus service with the well-known + name org.freedesktop.UPower using + the + EnumerateDevices + method. + + + + +$ dbus-send --print-reply \ + --system \ + --dest=org.freedesktop.UPower \ + /org/freedesktop/UPower/devices/battery_BAT0 \ + org.freedesktop.DBus.Properties.GetAll \ + string:org.freedesktop.UPower.Device + +method return sender=:1.386 -> dest=:1.477 reply_serial=2 + array [ + dict entry( + string "native-path" + variant string "/sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0" + ) + dict entry( + string "vendor" + variant string "SONY" + ) + dict entry( + string "model" + variant string "42T4568" + ) + dict entry( + string "serial" + variant string "4179" + ) + dict entry( + string "update-time" + variant uint64 1226417875 + ) + dict entry( + string "type" + variant uint 2 + ) + dict entry( + string "power-supply" + variant boolean true + ) + dict entry( + string "has-history" + variant boolean true + ) + dict entry( + string "has-statistics" + variant boolean true + ) + dict entry( + string "online" + variant boolean false + ) + dict entry( + string "energy" + variant double 72.85 + ) + dict entry( + string "energy-empty" + variant double 0 + ) + dict entry( + string "energy-full" + variant double 74.55 + ) + dict entry( + string "energy-full-design" + variant double 74.88 + ) + dict entry( + string "energy-rate" + variant double 0 + ) + dict entry( + string "voltage" + variant double 16.415 + ) + dict entry( + string "time-to-empty" + variant int64 0 + ) + dict entry( + string "time-to-full" + variant int64 0 + ) + dict entry( + string "percentage" + variant double 97.7197 + ) + dict entry( + string "is-present" + variant boolean true + ) + dict entry( + string "state" + variant uint 3 + ) + dict entry( + string "is-rechargeable" + variant boolean true + ) + dict entry( + string "capacity" + variant double 100 + ) + dict entry( + string "technology" + variant uint 1 + ) + ] + + + + + Unless otherwise noted, an empty string or the value 0 in a + property on this interface means not set. + + + + + + + + + + + + Refreshes the data collected from the power source. + + + Callers need the org.freedesktop.upower.refresh-power-source authorization + + if an error occured while refreshing + + + + + + + + + + Some value on the power source changed. + + + + + + + + + + The type of history. + Valid types are rate or charge. + + + The amount of data to return in seconds, or 0 for all. + + + + + The approximate number of points to return. + A higher resolution is more accurate, at the expense of plotting speed. + + + + + + The history data for the power device, if the device supports history. + Data is ordered from the earliest in time, to the newest data point. + Each element contains the following members: + + + time + + The time value in seconds from the gettimeofday() method. + + + + value + + The data value, for instance the rate in W or the charge in %. + + + + state + + The state of the device, for instance charging or + discharging. + + + + + + + + + Gets history for the power device that is persistent across reboots. + + + + + + + + + + The mode for the statistics. + Valid types are charging or discharging. + + + + The statistics data for the power device. + Each element contains the following members: + + + value + + The value of the percentage point, usually in seconds + + + + accuracy + + The accuracy of the prediction in percent. + + + + + + + + + Gets statistics for the power device that may be interesting + to show on a graph in the session. + + + + + + + + + + + OS specific native path of the power source. On Linux this + is the sysfs path, for + example /sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0. Is + blank if the device is being driven by a user space + driver. + + + + + + + + + + Name of the vendor of the battery. + + + + + + + + + + Name of the model of this battery. + + + + + + + + + + Unique serial number of the battery. + + + + + + + + + + The point in time (seconds since the Epoch Jan 1, 1970 + 0:00 UTC) that data was read from the power source. + + + + + + + + + + Type of power source. + + + + 0Unknown + + + 1Line Power + + + 2Battery + + + 3Ups + + + 4Monitor + + + 5Mouse + + + 6Keyboard + + + 7Pda + + + 8Phone + + + + + + + + + + + If the power device is used to supply the system. + This would be set TRUE for laptop batteries and UPS devices, + but set FALSE for wireless mice or PDAs. + + + + + + + + + + If the power device has history. + + + + + + + + + + If the power device has statistics. + + + + + + + + + + Whether power is currently being provided through line power. + This property is only valid if the property + type + has the value "line-power". + + + + + + + + + + Amount of energy (measured in Wh) currently available in + the power source. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Amount of energy (measured in Wh) in the power source when + it's considered to be empty. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Amount of energy (measured in Wh) in the power source when + it's considered full. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Amount of energy (measured in Wh) the power source is + designed to hold when it's considered full. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Amount of energy being drained from the source, measured + in W. If positive, the source is being discharged, if + negative it's being charged. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Voltage in the Cell or being recorded by the meter. + + + + + + + + + + Number of seconds until the power source is considered empty. + Is set to 0 if unknown. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Number of seconds until the power source is considered full. + Is set to 0 if unknown. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + The amount of energy left in the power source expressed as + a percentage between 0 and 100. Typically this is the same as + (energy - + energy-empty) / + (energy-full - + energy-empty). + However, some primitive power sources are capable of only + reporting percentages and in this case the energy-* + properties will be unset while this property is set. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + If the power source is present in the bay. + This field is required as some batteries are hot-removable, for example + expensive UPS and most laptop batteries. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + The battery power state. + + + + 0Unknown + + + 1Charging + + + 2Discharging + + + 3Empty + + + 4Fully charged + + + 5Pending charge + + + 6Pending discharge + + + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + If the power source is rechargeable. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + The capacity of the power source expressed as a percentage between 0 and 100. + The capacity of the battery will reduce with age. + A capacity value less than 75% is usually a sign that you should renew your battery. + Typically this value is the same as + (full-design / + full) * 100. + However, some primitive power sources are not capable reporting capacity + and in this case the capacity property will be unset. + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + Technology used in the battery: + + + + 0Unknown + + + 1Lithium ion + + + 2Lithium polymer + + + 3Lithium iron phosphate + + + 4Lead acid + + + 5Nickel cadmium + + + 6Nickel metal hydride + + + + This property is only valid if the property + type + has the value "battery". + + + + + + + + + + If the device may have been recalled by the vendor due to a suspected + fault. + This key does not imply the device is faulty, only that it approximatly + matches the description from the vendor of units that were recalled. + + + + + + + + + + The vendor that is handling the hardware recall. + + + This property is only valid if the property recall-notice is true. + + + + + + + + + + The URL to visit about the hardware recall. + + + This property is only valid if the property recall-notice is true. + + + + + + + + diff --git a/src/org.freedesktop.UPower.xml b/src/org.freedesktop.UPower.xml new file mode 100644 index 0000000..7b73583 --- /dev/null +++ b/src/org.freedesktop.UPower.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From f3deb18b47aa55364311ff13e2c69c07d25554d0 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:05:40 -0500 Subject: remove the org.gnome.SettingsDaemon listener; we'll use UPower directly --- src/dbus-listener.c | 247 ---------------------------------------------------- src/dbus-listener.h | 82 ----------------- 2 files changed, 329 deletions(-) delete mode 100644 src/dbus-listener.c delete mode 100644 src/dbus-listener.h diff --git a/src/dbus-listener.c b/src/dbus-listener.c deleted file mode 100644 index b1f64a7..0000000 --- a/src/dbus-listener.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - -Listens on DBus for Power changes and passes them to an IndicatorPower - -Copyright 2012 Canonical Ltd. - -Authors: - Charles Kerr - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 3.0 as published by the Free Software Foundation. - -This library 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 version 3.0 for more details. - -You should have received a copy of the GNU General Public -License along with this library. If not, see -. -*/ - -#include "dbus-listener.h" -#include "device.h" - -struct _IndicatorPowerDbusListenerPrivate -{ - GCancellable * cancellable; - GDBusProxy * proxy; - guint watcher_id; -}; - -#define INDICATOR_POWER_DBUS_LISTENER_GET_PRIVATE(o) (INDICATOR_POWER_DBUS_LISTENER(o)->priv) - -/* Signals */ -enum { - SIGNAL_DEVICES, - SIGNAL_LAST -}; -static guint signals[SIGNAL_LAST] = { 0 }; - - -/* GObject stuff */ -static void indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass); -static void indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self); -static void indicator_power_dbus_listener_dispose (GObject *object); -static void indicator_power_dbus_listener_finalize (GObject *object); - -static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data); - -/* LCOV_EXCL_START */ -G_DEFINE_TYPE (IndicatorPowerDbusListener, indicator_power_dbus_listener, G_TYPE_OBJECT); -/* LCOV_EXCL_STOP */ - -static void -indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (IndicatorPowerDbusListenerPrivate)); - - /* methods */ - object_class->dispose = indicator_power_dbus_listener_dispose; - object_class->finalize = indicator_power_dbus_listener_finalize; - - /** - * IndicatorPowerDbusListener::devices-enumerated: - * - * @listener: the IndicatorPowerDbusListener - * @devices: a GSList of #IndicatorPowerDevice objects. (transfer none) - * - * This is emitted each time a new set of devices is enumerated over the bus. - */ - signals[SIGNAL_DEVICES] = g_signal_new (INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, - G_TYPE_FROM_CLASS(klass), 0, - G_STRUCT_OFFSET (IndicatorPowerDbusListenerClass, devices_enumerated), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} - -/* Initialize an instance */ -static void -indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self) -{ - IndicatorPowerDbusListenerPrivate * priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - INDICATOR_POWER_DBUS_LISTENER_TYPE, - IndicatorPowerDbusListenerPrivate); - - priv->cancellable = g_cancellable_new (); - - priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, - GSD_SERVICE, - G_BUS_NAME_WATCHER_FLAGS_NONE, - gsd_appeared_callback, - NULL, - self, - NULL); - - self->priv = priv; -} - -static void -indicator_power_dbus_listener_dispose (GObject *object) -{ - IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(object); - IndicatorPowerDbusListenerPrivate * priv = self->priv; - - g_clear_object (&priv->proxy); - - if (priv->cancellable != NULL) - { - g_cancellable_cancel (priv->cancellable); - g_clear_object (&priv->cancellable); - } - - if (priv->watcher_id) - { - g_bus_unwatch_name (priv->watcher_id); - priv->watcher_id = 0; - } - - G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->dispose (object); -} - -static void -indicator_power_dbus_listener_finalize (GObject *object) -{ - G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->finalize (object); -} - -/*** -**** -***/ - -static void -get_devices_cb (GObject * source_object, - GAsyncResult * res, - gpointer user_data) -{ - GError *error; - GSList * devices = NULL; - GVariant * devices_container; - IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER (user_data); - - /* build an array of IndicatorPowerDevices from the DBus response */ - error = NULL; - devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); - if (devices_container == NULL) - { - g_message ("Couldn't get devices: %s\n", error->message); - g_error_free (error); - } - else - { - gsize i; - GVariant * devices_variant = g_variant_get_child_value (devices_container, 0); - const int device_count = devices_variant ? g_variant_n_children (devices_variant) : 0; - - for (i=0; ipriv->proxy, - "GetDevices", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - self->priv->cancellable, - get_devices_cb, - self); -} - -static void -receive_properties_changed (GDBusProxy *proxy G_GNUC_UNUSED, - GVariant *changed_properties G_GNUC_UNUSED, - GStrv invalidated_properties G_GNUC_UNUSED, - gpointer user_data) -{ - request_device_list (INDICATOR_POWER_DBUS_LISTENER(user_data)); -} - - -static void -service_proxy_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) -{ - GError * error = NULL; - IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); - IndicatorPowerDbusListenerPrivate * priv = self->priv; - - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (error != NULL) - { - g_error ("Error creating proxy: %s", error->message); - g_error_free (error); - return; - } - - /* we want to change the primary device changes */ - g_signal_connect (priv->proxy, "g-properties-changed", - G_CALLBACK (receive_properties_changed), user_data); - - /* get the initial state */ - request_device_list (self); -} - -static void -gsd_appeared_callback (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); - IndicatorPowerDbusListenerPrivate * priv = self->priv; - - g_dbus_proxy_new (connection, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - name, - GSD_POWER_DBUS_PATH, - GSD_POWER_DBUS_INTERFACE, - priv->cancellable, - service_proxy_cb, - self); -} diff --git a/src/dbus-listener.h b/src/dbus-listener.h deleted file mode 100644 index e4d006b..0000000 --- a/src/dbus-listener.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - -Listens for Power changes from org.gnome.SettingsDaemon.Power on Dbus - -Copyright 2012 Canonical Ltd. - -Authors: - Javier Jardon - Charles Kerr - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 3.0 as published by the Free Software Foundation. - -This library 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 version 3.0 for more details. - -You should have received a copy of the GNU General Public -License along with this library. If not, see -. -*/ - -#ifndef __INDICATOR_POWER_DBUS_LISTENER_H__ -#define __INDICATOR_POWER_DBUS_LISTENER_H__ - -#include -#include - -G_BEGIN_DECLS - -#define INDICATOR_POWER_DBUS_LISTENER_TYPE (indicator_power_dbus_listener_get_type ()) -#define INDICATOR_POWER_DBUS_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListener)) -#define INDICATOR_POWER_DBUS_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListenerClass)) -#define INDICATOR_IS_POWER_DBUS_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE)) -#define INDICATOR_IS_POWER_DBUS_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_DBUS_LISTENER_TYPE)) -#define INDICATOR_POWER_DBUS_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListenerClass)) - -typedef struct _IndicatorPowerDbusListener IndicatorPowerDbusListener; -typedef struct _IndicatorPowerDbusListenerClass IndicatorPowerDbusListenerClass; -typedef struct _IndicatorPowerDbusListenerPrivate IndicatorPowerDbusListenerPrivate; - -#define GSD_SERVICE "org.gnome.SettingsDaemon" -#define GSD_PATH "/org/gnome/SettingsDaemon" -#define GSD_POWER_DBUS_INTERFACE GSD_SERVICE ".Power" -#define GSD_POWER_DBUS_PATH GSD_PATH "/Power" - -/* signals */ -#define INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED "devices-enumerated" - -/** - * IndicatorPowerDbusListenerClass: - * @parent_class: #GObjectClass - */ -struct _IndicatorPowerDbusListenerClass -{ - GObjectClass parent_class; - - void (* devices_enumerated) (IndicatorPowerDbusListener*, GSList * devices); -}; - -/** - * IndicatorPowerDbusListener: - * @parent: #GObject - * @priv: A cached reference to the private data for the instance. -*/ -struct _IndicatorPowerDbusListener -{ - GObject parent; - IndicatorPowerDbusListenerPrivate * priv; -}; - -/*** -**** -***/ - -GType indicator_power_dbus_listener_get_type (void); - -G_END_DECLS - -#endif -- cgit v1.2.3 From ebde9c59e9cb8af90dc760df2fada7a33c9a74df Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:07:59 -0500 Subject: add device-provider, an interface class for an object that provides IndicatorPowerDevices. This could be given a UPower implementation, or a mock implementation, or a whatever-replaces-upower-on-phones implementation. --- src/device-provider.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/device-provider.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/device-provider.c create mode 100644 src/device-provider.h diff --git a/src/device-provider.c b/src/device-provider.c new file mode 100644 index 0000000..361ab3c --- /dev/null +++ b/src/device-provider.c @@ -0,0 +1,81 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#include "device-provider.h" + +enum +{ + SIGNAL_DEVICES_CHANGED, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = { 0 }; + +G_DEFINE_INTERFACE (IndicatorPowerDeviceProvider, + indicator_power_device_provider, + 0); + +static void +indicator_power_device_provider_default_init (IndicatorPowerDeviceProviderInterface * klass) +{ + signals[SIGNAL_DEVICES_CHANGED] = g_signal_new ( + "devices-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorPowerDeviceProviderInterface, devices_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +/*** +**** PUBLIC API +***/ + +/** + * Get a list of devices + * + * An easy way to free the list properly in one step is as follows: + * + * g_slist_free_full (list, (GDestroyNotify)g_object_unref); + * + * Return value: (element-type IndicatorPowerDevice) + * (transfer full): + * list of devices + */ +GList * +indicator_power_device_provider_get_devices (IndicatorPowerDeviceProvider * self) +{ + g_return_if_fail (INDICATOR_IS_POWER_DEVICE_PROVIDER (self)); + + return INDICATOR_POWER_DEVICE_PROVIDER_GET_INTERFACE (self)->get_devices (self); +} + +/** + * Emits the "devices-changed" signal. + * + * This should only be called by subclasses. + */ +void +indicator_power_device_provider_emit_devices_changed (IndicatorPowerDeviceProvider * self) +{ + g_return_if_fail (INDICATOR_IS_POWER_DEVICE_PROVIDER (self)); + + g_signal_emit (self, signals[SIGNAL_DEVICES_CHANGED], 0, NULL); +} diff --git a/src/device-provider.h b/src/device-provider.h new file mode 100644 index 0000000..edef6f2 --- /dev/null +++ b/src/device-provider.h @@ -0,0 +1,80 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#ifndef __INDICATOR_POWER_DEVICE_PROVIDER__H__ +#define __INDICATOR_POWER_DEVICE_PROVIDER__H__ + +#include + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_DEVICE_PROVIDER \ + (indicator_power_device_provider_get_type ()) + +#define INDICATOR_POWER_DEVICE_PROVIDER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + INDICATOR_TYPE_POWER_DEVICE_PROVIDER, \ + IndicatorPowerDeviceProvider)) + +#define INDICATOR_IS_POWER_DEVICE_PROVIDER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_POWER_DEVICE_PROVIDER)) + +#define INDICATOR_POWER_DEVICE_PROVIDER_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + INDICATOR_TYPE_POWER_DEVICE_PROVIDER, \ + IndicatorPowerDeviceProviderInterface)) + +typedef struct _IndicatorPowerDeviceProvider + IndicatorPowerDeviceProvider; + +typedef struct _IndicatorPowerDeviceProviderInterface + IndicatorPowerDeviceProviderInterface; + +/** + * An interface class for an object that provides IndicatorPowerDevices. + * + * Example uses: + * - in unit tests, a mock that feeds fake devices to the service + * - in production, an implementation that monitors upower + * - in the future, upower can be replaced by changing providers + */ +struct _IndicatorPowerDeviceProviderInterface +{ + GTypeInterface parent_iface; + + /* signals */ + void (*devices_changed) (IndicatorPowerDeviceProvider * self); + + /* virtual functions */ + GList* (*get_devices) (IndicatorPowerDeviceProvider * self); +}; + +GType indicator_power_device_provider_get_type (void); + +/*** +**** +***/ + +GList * indicator_power_device_provider_get_devices (IndicatorPowerDeviceProvider * self); + +void indicator_power_device_provider_emit_devices_changed (IndicatorPowerDeviceProvider * self); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_DEVICE_PROVIDER__H__ */ -- cgit v1.2.3 From da79f94b45b12154b89d3a095844f97115769558 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:08:21 -0500 Subject: add device-provider-upower, a UPower implementation of device-provider --- src/device-provider-upower.c | 364 +++++++++++++++++++++++++++++++++++++++++++ src/device-provider-upower.h | 72 +++++++++ 2 files changed, 436 insertions(+) create mode 100644 src/device-provider-upower.c create mode 100644 src/device-provider-upower.h diff --git a/src/device-provider-upower.c b/src/device-provider-upower.c new file mode 100644 index 0000000..850717e --- /dev/null +++ b/src/device-provider-upower.c @@ -0,0 +1,364 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#include "config.h" + +#include "dbus-upower.h" +#include "dbus-upower-device.h" +#include "device.h" +#include "device-provider.h" +#include "device-provider-upower.h" + +#define BUS_NAME "org.freedesktop.UPower" +#define BUS_PATH "/org/freedesktop/UPower" + +/*** +**** private struct +***/ + +struct _IndicatorPowerDeviceProviderUPowerPriv +{ + DbusUPower * upower_proxy; + GHashTable * devices; + GCancellable * cancellable; + guint timer; +}; + +typedef IndicatorPowerDeviceProviderUPowerPriv priv_t; + +/*** +**** GObject boilerplate +***/ + +static void indicator_power_device_provider_interface_init ( + IndicatorPowerDeviceProviderInterface * iface); + +G_DEFINE_TYPE_WITH_CODE ( + IndicatorPowerDeviceProviderUPower, + indicator_power_device_provider_upower, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_DEVICE_PROVIDER, + indicator_power_device_provider_interface_init)); + +/*** +**** TIMER +***/ + +/* + * Rebuilds are needed whenever upower devices are added, changed, or removed. + * + * Events often come in batches. For example, unplugging a power cable + * triggers a device-removed signal, and also a device-changed as the + * battery's state changes to 'discharging'. + * + * We use a small timer here to fold upower events into a single + * IndicatorPowerDeviceProvider devices-changed signal. + */ + +static gboolean +on_timer (gpointer gself) +{ + IndicatorPowerDeviceProvider * provider; + IndicatorPowerDeviceProviderUPower * provider_upower; + + provider = INDICATOR_POWER_DEVICE_PROVIDER (gself); + indicator_power_device_provider_emit_devices_changed (provider); + + provider_upower = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); + provider_upower->priv->timer = 0; + return G_SOURCE_REMOVE; +} + +static void +emit_devices_changed_soon (IndicatorPowerDeviceProviderUPower * self) +{ + if (self->priv->timer == 0) + self->priv->timer = g_timeout_add_seconds (1, on_timer, self); +} + +/*** +**** UPOWER DBUS +***/ + +static void +on_upower_device_proxy_ready (GObject * o, GAsyncResult * res, gpointer gself) +{ + GError * err; + DbusDevice * tmp; + + err = NULL; + tmp = dbus_device_proxy_new_for_bus_finish (res, &err); + if (err != NULL) + { + g_warning ("Unable to get UPower Device Proxy: %s", err->message); + g_error_free (err); + } + else + { + IndicatorPowerDevice * device; + IndicatorPowerDeviceProviderUPower * self; + priv_t * p; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); + p = self->priv; + + const guint kind = dbus_device_get_type_ (tmp); + const gdouble percentage = dbus_device_get_percentage (tmp); + const guint state = dbus_device_get_state (tmp); + const gint64 time_to_empty = dbus_device_get_time_to_empty (tmp); + const gint64 time_to_full = dbus_device_get_time_to_full (tmp); + const time_t time = time_to_empty ? time_to_empty : time_to_full; + const char * path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (tmp)); + + device = indicator_power_device_new (path, + kind, + percentage, + state, + time); + + g_hash_table_insert (p->devices, + g_strdup (path), + g_object_ref (device)); + + emit_devices_changed_soon (self); + + g_object_unref (device); + g_object_unref (tmp); + } +} + +static void +update_device_from_object_path (IndicatorPowerDeviceProviderUPower * self, + const char * path) +{ + dbus_device_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + BUS_NAME, + path, + self->priv->cancellable, + on_upower_device_proxy_ready, + self); +} + +static void +on_upower_device_enumerations_ready (GObject * proxy, + GAsyncResult * res, + gpointer gself) +{ + GError * err; + char ** object_paths; + + err = NULL; + dbus_upower_call_enumerate_devices_finish (DBUS_UPOWER(proxy), + &object_paths, + res, + &err); + + if (err != NULL) + { + g_warning ("Unable to get UPower devices: %s", err->message); + g_error_free (err); + } + else + { + guint i; + + for (i=0; object_paths && object_paths[i]; i++) + update_device_from_object_path (gself, object_paths[i]); + + g_strfreev (object_paths); + } +} + +static void +on_upower_device_added (DbusUPower * unused G_GNUC_UNUSED, + const char * object_path, + gpointer gself) +{ + update_device_from_object_path (gself, object_path); +} + +static void +on_upower_device_changed (DbusUPower * unused G_GNUC_UNUSED, + const char * object_path, + gpointer gself) +{ + update_device_from_object_path (gself, object_path); +} + +static void +on_upower_device_removed (DbusUPower * unused G_GNUC_UNUSED, + const char * object_path, + gpointer gself) +{ + IndicatorPowerDeviceProviderUPower * self; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); + g_hash_table_remove (self->priv->devices, object_path); + emit_devices_changed_soon (self); +} + +static void +on_upower_proxy_ready (GObject * source G_GNUC_UNUSED, + GAsyncResult * res, + gpointer gself) +{ + GError * err; + DbusUPower * proxy; + + err = NULL; + proxy = dbus_upower_proxy_new_for_bus_finish (res, &err); + if (err != NULL) + { + g_warning ("Unable to get UPower proxy: %s", err->message); + g_error_free (err); + } + else + { + IndicatorPowerDeviceProviderUPower * self; + priv_t * p; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); + p = self->priv; + + p->upower_proxy = proxy; + g_signal_connect (proxy, "device-changed", + G_CALLBACK (on_upower_device_changed), self); + g_signal_connect (proxy, "device-added", + G_CALLBACK (on_upower_device_added), self); + g_signal_connect (proxy, "device-removed", + G_CALLBACK (on_upower_device_removed), self); + + dbus_upower_call_enumerate_devices (p->upower_proxy, + p->cancellable, + on_upower_device_enumerations_ready, + self); + } +} + +/*** +**** IndicatorPowerDeviceProvider virtual functions +***/ + +static GList * +my_get_devices (IndicatorPowerDeviceProvider * provider) +{ + GList * devices; + IndicatorPowerDeviceProviderUPower * self; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(provider); + + devices = g_hash_table_get_values (self->priv->devices); + g_list_foreach (devices, (GFunc)g_object_ref, NULL); + return devices; +} + +/*** +**** GObject virtual functions +***/ + +static void +my_dispose (GObject * o) +{ + IndicatorPowerDeviceProviderUPower * self; + priv_t * p; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(o); + p = self->priv; + + if (p->cancellable != NULL) + { + g_cancellable_cancel (p->cancellable); + + g_clear_object (&p->cancellable); + } + + if (p->timer != 0) + { + g_source_remove (p->timer); + + p->timer = 0; + } + + g_clear_object (&p->upower_proxy); + + g_clear_pointer (&p->devices, g_hash_table_destroy); + + G_OBJECT_CLASS (indicator_power_device_provider_upower_parent_class)->dispose (o); +} + +/*** +**** Instantiation +***/ + +static void +indicator_power_device_provider_upower_class_init (IndicatorPowerDeviceProviderUPowerClass * klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = my_dispose; + + g_type_class_add_private (klass, + sizeof (IndicatorPowerDeviceProviderUPowerPriv)); +} + +static void +indicator_power_device_provider_interface_init (IndicatorPowerDeviceProviderInterface * iface) +{ + iface->get_devices = my_get_devices; +} + +static void +indicator_power_device_provider_upower_init (IndicatorPowerDeviceProviderUPower * self) +{ + IndicatorPowerDeviceProviderUPowerPriv * p; + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER, + IndicatorPowerDeviceProviderUPowerPriv); + + self->priv = p; + + p->cancellable = g_cancellable_new (); + + p->devices = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + dbus_upower_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, + BUS_NAME, + BUS_PATH, + p->cancellable, + on_upower_proxy_ready, + self); +} + +/*** +**** Public API +***/ + +IndicatorPowerDeviceProvider * +indicator_power_device_provider_upower_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER, NULL); + + return INDICATOR_POWER_DEVICE_PROVIDER (o); +} diff --git a/src/device-provider-upower.h b/src/device-provider-upower.h new file mode 100644 index 0000000..7bdd5d5 --- /dev/null +++ b/src/device-provider-upower.h @@ -0,0 +1,72 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#ifndef __INDICATOR_POWER_DEVICE_PROVIDER_UPOWER__H__ +#define __INDICATOR_POWER_DEVICE_PROVIDER_UPOWER__H__ + +#include /* parent class */ + +#include "device-provider.h" + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER \ + (indicator_power_device_provider_upower_get_type()) + +#define INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER, \ + IndicatorPowerDeviceProviderUPower)) + +#define INDICATOR_POWER_DEVICE_PROVIDER_UPOWER_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER, \ + IndicatorPowerDeviceProviderUPowerClass)) + +#define INDICATOR_IS_POWER_DEVICE_PROVIDER_UPOWER(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + INDICATOR_TYPE_POWER_DEVICE_PROVIDER_UPOWER)) + +typedef struct _IndicatorPowerDeviceProviderUPower + IndicatorPowerDeviceProviderUPower; +typedef struct _IndicatorPowerDeviceProviderUPowerPriv + IndicatorPowerDeviceProviderUPowerPriv; +typedef struct _IndicatorPowerDeviceProviderUPowerClass + IndicatorPowerDeviceProviderUPowerClass; + +/** + * An IndicatorPowerDeviceProvider which gets its devices from UPower. + */ +struct _IndicatorPowerDeviceProviderUPower +{ + GObject parent_instance; + + IndicatorPowerDeviceProviderUPowerPriv * priv; +}; + +struct _IndicatorPowerDeviceProviderUPowerClass +{ + GObjectClass parent_class; +}; + +IndicatorPowerDeviceProvider * indicator_power_device_provider_upower_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_DEVICE_PROVIDER_UPOWER__H__ */ -- cgit v1.2.3 From ee13ae6fa34d0bc0330bdd68c11a6d8b62e44cfd Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:09:09 -0500 Subject: add the heart of the service --- src/service.c | 1053 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/service.h | 79 +++++ 2 files changed, 1132 insertions(+) create mode 100644 src/service.c create mode 100644 src/service.h diff --git a/src/service.c b/src/service.c new file mode 100644 index 0000000..5aabefc --- /dev/null +++ b/src/service.c @@ -0,0 +1,1053 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * Ted Gould + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#include "config.h" + +#include +#include + +#include "device.h" +#include "device-provider.h" +#include "service.h" + +#define BUS_NAME "power.indicator" +#define BUS_PATH "/com/canonical/indicator/power" + +#define SETTINGS_SHOW_TIME_S "show-time" +#define SETTINGS_ICON_POLICY_S "icon-policy" + +G_DEFINE_TYPE (IndicatorPowerService, + indicator_power_service, + G_TYPE_OBJECT) + +enum +{ + SIGNAL_NAME_LOST, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum +{ + PROP_0, + PROP_REPLACE, + PROP_DEVICE_PROVIDER, + PROP_LAST +}; + +static GParamSpec * properties[PROP_LAST]; + +enum +{ + SECTION_HEADER = (1<<0), + SECTION_DEVICES = (1<<1), + SECTION_SETTINGS = (1<<2), +}; + +enum +{ + PROFILE_DESKTOP, + PROFILE_GREETER, + N_PROFILES +}; + +static const char * const menu_names[N_PROFILES] = +{ + "desktop", + "greeter" +}; + +enum +{ + POWER_INDICATOR_ICON_POLICY_PRESENT, + POWER_INDICATOR_ICON_POLICY_CHARGE, + POWER_INDICATOR_ICON_POLICY_NEVER +}; + +struct ProfileMenuInfo +{ + /* the root level -- the header is the only child of this */ + GMenu * menu; + + /* parent of the sections. This is the header's submenu */ + GMenu * submenu; + + guint export_id; +}; + +struct _IndicatorPowerServicePrivate +{ + GCancellable * cancellable; + + GSettings * settings; + + guint own_id; + guint actions_export_id; + GDBusConnection * conn; + + struct ProfileMenuInfo menus[N_PROFILES]; + + GSimpleActionGroup * actions; + GSimpleAction * header_action; + GSimpleAction * show_time_action; + + gboolean replace; + + IndicatorPowerDevice * primary_device; + GList * devices; /* IndicatorPowerDevice */ + + IndicatorPowerDeviceProvider * device_provider; +}; + +typedef IndicatorPowerServicePrivate priv_t; + +/*** +**** +***/ + +static void rebuild_now (IndicatorPowerService * self, guint section); + +static inline void +rebuild_header_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_HEADER); +} + +static inline void +rebuild_devices_section_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_DEVICES); +} + +static inline void +rebuild_settings_section_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_SETTINGS); +} + +/*** +**** +**** DEVICES +**** +***/ + +/* the higher the weight, the more interesting the device */ +static int +get_device_kind_weight (const IndicatorPowerDevice * device) +{ + UpDeviceKind kind; + static gboolean initialized = FALSE; + static int weights[UP_DEVICE_KIND_LAST]; + + kind = indicator_power_device_get_kind (device); + g_return_val_if_fail (0<=kind && kind b_time ? -1 : 1; + else + ret = a_percentage < b_percentage ? -1 : 1; + } + } + + if (!ret) /* neither device is charging nor discharging... */ + { + const int weight_a = get_device_kind_weight (a); + const int weight_b = get_device_kind_weight (b); + + if (weight_a > weight_b) + { + ret = -1; + } + else if (weight_a < weight_b) + { + ret = 1; + } + } + + if (!ret) + ret = a_state - b_state; + + return ret; +} + +static void +dispose_devices (IndicatorPowerService * self) +{ + priv_t * p = self->priv; + + g_clear_object (&p->primary_device); + g_list_free_full (p->devices, g_object_unref); + p->devices = NULL; +} + +static void +on_devices_changed (IndicatorPowerService * self) +{ + priv_t * p = self->priv; + + /* update the device list */ + g_list_free_full (p->devices, (GDestroyNotify)g_object_unref); + p->devices = indicator_power_device_provider_get_devices (p->device_provider); + + /* update the primary device */ + g_clear_object (&p->primary_device); + p->primary_device = indicator_power_service_choose_primary_device (p->devices); + + rebuild_now (self, SECTION_HEADER | SECTION_DEVICES); +} + +/*** +**** +**** HEADER SECTION +**** +***/ + +static void +count_batteries (GList * devices, int *total, int *inuse) +{ + GList * l; + + for (l=devices; l!=NULL; l=l->next) + { + const IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); + + if (indicator_power_device_get_kind(device) == UP_DEVICE_KIND_BATTERY || + indicator_power_device_get_kind(device) == UP_DEVICE_KIND_UPS) + { + ++*total; + + const UpDeviceState state = indicator_power_device_get_state (device); + if ((state == UP_DEVICE_STATE_CHARGING) || + (state == UP_DEVICE_STATE_DISCHARGING)) + ++*inuse; + } + } + + g_debug ("count_batteries found %d batteries (%d are charging/discharging)", + *total, *inuse); +} + +static gboolean +should_be_visible (IndicatorPowerService * self) +{ + gboolean visible = TRUE; + priv_t * p = self->priv; + + const int policy = g_settings_get_enum (p->settings, SETTINGS_ICON_POLICY_S); + g_debug ("policy is: %d (present==0, charge==1, never==2)", policy); + + if (policy == POWER_INDICATOR_ICON_POLICY_NEVER) + { + visible = FALSE; + } + else + { + int batteries=0, inuse=0; + + count_batteries (p->devices, &batteries, &inuse); + + if (policy == POWER_INDICATOR_ICON_POLICY_PRESENT) + { + visible = batteries > 0; + } + else if (policy == POWER_INDICATOR_ICON_POLICY_CHARGE) + { + visible = inuse > 0; + } + } + + g_debug ("should_be_visible: %s", visible?"yes":"no"); + return visible; +} + +static GVariant * +create_header_state (IndicatorPowerService * self) +{ + GVariantBuilder b; + gchar * label = NULL; + gchar * a11y = NULL; + GIcon * icon = NULL; + priv_t * p = self->priv; + + if (p->primary_device != NULL) + { + gchar * details; + + indicator_power_device_get_time_details (p->primary_device, + &label, + &details, + &a11y); + + icon = indicator_power_device_get_gicon (p->primary_device); + + g_free (details); + } + + g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add (&b, "{sv}", "visible", + g_variant_new_boolean (should_be_visible (self))); + + if (label != NULL) + { + if (g_settings_get_boolean (p->settings, SETTINGS_SHOW_TIME_S)) + g_variant_builder_add (&b, "{sv}", "label", + g_variant_new_string (label)); + + g_free (label); + } + + if (icon != NULL) + { + g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); + + g_object_unref (icon); + } + + if (a11y != NULL) + { + g_variant_builder_add (&b, "{sv}", "accessible-desc", + g_variant_new_string (a11y)); + + g_free (a11y); + } + + return g_variant_builder_end (&b); +} + + +/*** +**** +**** DEVICE SECTION +**** +***/ + +static void +append_device_to_menu (GMenu * menu, const IndicatorPowerDevice * device) +{ + const UpDeviceKind kind = indicator_power_device_get_kind (device); + + if (kind != UP_DEVICE_KIND_LINE_POWER) + { + char * brief; + char * label; + char * a11y; + GMenuItem * menu_item; + GIcon * icon = indicator_power_device_get_gicon (device); + + indicator_power_device_get_time_details (device, + &brief, + &label, + &a11y); + + menu_item = g_menu_item_new (label, "indicator.activate-statistics"); + + if (icon != NULL) + { + g_menu_item_set_attribute_value (menu_item, + G_MENU_ATTRIBUTE_ICON, + g_icon_serialize (icon)); + } + + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); + + g_clear_object (&icon); + g_free (brief); + g_free (label); + g_free (a11y); + } +} + + +static GMenuModel * +create_devices_section (IndicatorPowerService * self) +{ + GList * l; + GMenu * menu = g_menu_new (); + + for (l=self->priv->devices; l!=NULL; l=l->next) + append_device_to_menu (menu, l->data); + + return G_MENU_MODEL (menu); +} + + +/*** +**** +**** SETTINGS SECTION +**** +***/ + +static GMenuModel * +create_settings_section (IndicatorPowerService * self G_GNUC_UNUSED) +{ + GMenu * menu = g_menu_new (); + + g_menu_append (menu, + _("Show Time in Menu Bar"), + "indicator.show-time"); + + g_menu_append (menu, + _("Power Settings\342\200\246"), + "indicator.activate-settings"); + + return G_MENU_MODEL (menu); +} + +/*** +**** +**** +***/ + +/** + * A small helper function for rebuild_now(). + * - removes the previous section + * - adds and unrefs the new section + */ +static void +rebuild_section (GMenu * parent, int pos, GMenuModel * new_section) +{ + g_menu_remove (parent, pos); + g_menu_insert_section (parent, pos, NULL, new_section); + g_object_unref (new_section); +} + +static void +rebuild_now (IndicatorPowerService * self, guint sections) +{ + priv_t * p = self->priv; + struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP]; + struct ProfileMenuInfo * greeter = &p->menus[PROFILE_GREETER]; + + if (p->conn == NULL) /* we haven't built the menus yet */ + return; + + if (sections & SECTION_HEADER) + { + g_simple_action_set_state (p->header_action, create_header_state (self)); + } + + if (sections & SECTION_DEVICES) + { + rebuild_section (desktop->submenu, 0, create_devices_section (self)); + rebuild_section (greeter->submenu, 0, create_devices_section (self)); + } + + if (sections & SECTION_SETTINGS) + { + rebuild_section (desktop->submenu, 1, create_settings_section (self)); + } +} + +static void +create_menu (IndicatorPowerService * self, int profile) +{ + GMenu * menu; + GMenu * submenu; + GMenuItem * header; + GMenuModel * sections[16]; + guint i; + guint n = 0; + + g_assert (0<=profile && profilepriv->menus[profile].menu == NULL); + + if (profile == PROFILE_DESKTOP) + { + sections[n++] = create_devices_section (self); + sections[n++] = create_settings_section (self); + } + else if (profile == PROFILE_GREETER) + { + sections[n++] = create_devices_section (self); + } + + /* add sections to the submenu */ + + submenu = g_menu_new (); + + for (i=0; ipriv->menus[profile].menu = menu; + self->priv->menus[profile].submenu = submenu; +} + +/*** +**** GActions +***/ + +/* Run a particular program based on an activation */ +static void +execute_command (const gchar * cmd) +{ + GError * err = NULL; + + g_debug ("Issuing command '%s'", cmd); + + if (!g_spawn_command_line_async (cmd, &err)) + { + g_warning ("Unable to start %s: %s", cmd, err->message); + g_error_free (err); + } +} + +static void +on_settings_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself G_GNUC_UNUSED) +{ + execute_command ("gnome-control-center power"); +} + +static void +on_statistics_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself G_GNUC_UNUSED) +{ + execute_command ("gnome-power-statistics"); +} + +static void +set_show_time_flag (IndicatorPowerService * self, gboolean b) +{ + GVariant * v; + priv_t * p = self->priv; + + /* update the settings */ + if (b != g_settings_get_boolean (p->settings, SETTINGS_SHOW_TIME_S)) + g_settings_set_boolean (p->settings, SETTINGS_SHOW_TIME_S, b); + + /* update the action state */ + v = g_action_get_state (G_ACTION(p->show_time_action)); + if (b != g_variant_get_boolean (v)) + g_simple_action_set_state (p->show_time_action, g_variant_new_boolean (b)); + g_variant_unref (v); + + rebuild_header_now (self); +} +static void +on_show_time_setting_changed (GSettings * settings, gchar * key, gpointer gself) +{ + set_show_time_flag (gself, g_settings_get_boolean (settings, key)); +} +static void +on_show_time_action_state_changed (GAction * action, + GParamSpec * pspec G_GNUC_UNUSED, + gpointer gself) +{ + GVariant * v = g_action_get_state (action); + set_show_time_flag (gself, g_variant_get_boolean (v)); + g_variant_unref (v); +} + +/* toggles the state */ +static void +on_show_time_action_activated (GSimpleAction * simple, + GVariant * parameter G_GNUC_UNUSED, + gpointer unused G_GNUC_UNUSED) +{ + GVariant * v = g_action_get_state (G_ACTION (simple)); + gboolean flag = g_variant_get_boolean (v); + g_simple_action_set_state (simple, g_variant_new_boolean (!flag)); + g_variant_unref (v); +} + +static void +init_gactions (IndicatorPowerService * self) +{ + GSimpleAction * a; + gboolean show_time; + priv_t * p = self->priv; + + GActionEntry entries[] = { + { "activate-settings", on_settings_activated }, + { "activate-statistics", on_statistics_activated } + }; + + p->actions = g_simple_action_group_new (); + + g_action_map_add_action_entries (G_ACTION_MAP(p->actions), + entries, + G_N_ELEMENTS(entries), + self); + + /* add the header action */ + a = g_simple_action_new_stateful ("_header", NULL, create_header_state (self)); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->header_action = a; + + /* add the show-time action */ + show_time = g_settings_get_boolean (p->settings, SETTINGS_SHOW_TIME_S); + a = g_simple_action_new_stateful ("show-time", + NULL, + g_variant_new_boolean(show_time)); + g_signal_connect (a, "activate", + G_CALLBACK(on_show_time_action_activated), self); + g_signal_connect (a, "notify", + G_CALLBACK(on_show_time_action_state_changed), self); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->show_time_action = a; + + rebuild_header_now (self); +} + +/*** +**** GDBus +***/ + +static void +on_bus_acquired (GDBusConnection * connection, + const gchar * name, + gpointer gself) +{ + int i; + guint id; + GError * err = NULL; + IndicatorPowerService * self = INDICATOR_POWER_SERVICE(gself); + priv_t * p = self->priv; + GString * path = g_string_new (NULL); + + g_debug ("bus acquired: %s", name); + + p->conn = g_object_ref (G_OBJECT (connection)); + + /* export the actions */ + if ((id = g_dbus_connection_export_action_group (connection, + BUS_PATH, + G_ACTION_GROUP (p->actions), + &err))) + { + p->actions_export_id = id; + } + else + { + g_warning ("cannot export action group: %s", err->message); + g_clear_error (&err); + } + + /* export the menus */ + for (i=0; imenus[i]; + + g_string_printf (path, "%s/%s", BUS_PATH, menu_names[i]); + + if (menu->menu == NULL) + create_menu (self, i); + + if ((id = g_dbus_connection_export_menu_model (connection, + path->str, + G_MENU_MODEL (menu->menu), + &err))) + { + menu->export_id = id; + } + else + { + g_warning ("cannot export %s menu: %s", path->str, err->message); + g_clear_error (&err); + } + } + + g_string_free (path, TRUE); +} + +static void +unexport (IndicatorPowerService * self) +{ + int i; + priv_t * p = self->priv; + + /* unexport the menus */ + for (i=0; ipriv->menus[i].export_id; + + if (*id) + { + g_dbus_connection_unexport_menu_model (p->conn, *id); + *id = 0; + } + } + + /* unexport the actions */ + if (p->actions_export_id) + { + g_dbus_connection_unexport_action_group (p->conn, p->actions_export_id); + p->actions_export_id = 0; + } +} + +static void +on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, + const gchar * name, + gpointer gself) +{ + IndicatorPowerService * self = INDICATOR_POWER_SERVICE (gself); + + g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); + + unexport (self); + + g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); +} + + +/*** +**** GObject virtual functions +***/ + +static void +my_constructed (GObject * o) +{ + GBusNameOwnerFlags owner_flags; + IndicatorPowerService * self = INDICATOR_POWER_SERVICE(o); + priv_t * p = self->priv; + + /* own the name in constructed() instead of init() so that + we'll know the value of the 'replace' property */ + owner_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; + if (p->replace) + owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; + + p->own_id = g_bus_own_name (G_BUS_TYPE_SESSION, + BUS_NAME, + owner_flags, + on_bus_acquired, + NULL, + on_name_lost, + self, + NULL); +} + +static void +my_get_property (GObject * o, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorPowerService * self = INDICATOR_POWER_SERVICE (o); + priv_t * p = self->priv; + + switch (property_id) + { + case PROP_REPLACE: + g_value_set_boolean (value, p->replace); + break; + + case PROP_DEVICE_PROVIDER: + g_value_set_object (value, p->device_provider); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_set_property (GObject * o, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + IndicatorPowerService * self = INDICATOR_POWER_SERVICE (o); + + switch (property_id) + { + case PROP_REPLACE: + self->priv->replace = g_value_get_boolean (value); + break; + + case PROP_DEVICE_PROVIDER: + indicator_power_service_set_device_provider (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_dispose (GObject * o) +{ + IndicatorPowerService * self = INDICATOR_POWER_SERVICE(o); + priv_t * p = self->priv; + + if (p->own_id) + { + g_bus_unown_name (p->own_id); + p->own_id = 0; + } + + unexport (self); + + if (p->cancellable != NULL) + { + g_cancellable_cancel (p->cancellable); + g_clear_object (&p->cancellable); + } + + if (p->settings != NULL) + { + g_signal_handlers_disconnect_by_data (p->settings, self); + + g_clear_object (&p->settings); + } + + if (p->show_time_action != NULL) + { + g_signal_handlers_disconnect_by_data (p->show_time_action, self); + + g_clear_object (&p->show_time_action); + } + + g_clear_object (&p->header_action); + g_clear_object (&p->show_time_action); + g_clear_object (&p->actions); + + g_clear_object (&p->conn); + + indicator_power_service_set_device_provider (self, NULL); + + G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o); +} + +/*** +**** Instantiation +***/ + +static void +indicator_power_service_init (IndicatorPowerService * self) +{ + priv_t * p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_POWER_SERVICE, + IndicatorPowerServicePrivate); + self->priv = p; + + p->cancellable = g_cancellable_new (); + + p->settings = g_settings_new ("com.canonical.indicator.power"); + + init_gactions (self); + + g_signal_connect_swapped (p->settings, "changed::" SETTINGS_ICON_POLICY_S, + G_CALLBACK(rebuild_header_now), self); + g_signal_connect (p->settings, "changed::" SETTINGS_SHOW_TIME_S, + G_CALLBACK(on_show_time_setting_changed), self); +} + +static void +indicator_power_service_class_init (IndicatorPowerServiceClass * klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = my_dispose; + object_class->constructed = my_constructed; + object_class->get_property = my_get_property; + object_class->set_property = my_set_property; + + g_type_class_add_private (klass, sizeof (IndicatorPowerServicePrivate)); + + signals[SIGNAL_NAME_LOST] = g_signal_new ( + INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorPowerServiceClass, name_lost), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + properties[PROP_0] = NULL; + + properties[PROP_REPLACE] = g_param_spec_boolean ("replace", + "Replace Service", + "Replace existing service", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + properties[PROP_DEVICE_PROVIDER] = g_param_spec_object ("device-provider", + "Device Provider", + "Source for power devices", + G_TYPE_OBJECT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST, properties); +} + +/*** +**** Public API +***/ + +IndicatorPowerService * +indicator_power_service_new (gboolean replace, + IndicatorPowerDeviceProvider * device_provider) +{ + GObject * o = g_object_new (INDICATOR_TYPE_POWER_SERVICE, + "replace", replace, + "device-provider", device_provider, + NULL); + + return INDICATOR_POWER_SERVICE (o); +} + +void +indicator_power_service_set_device_provider (IndicatorPowerService * self, + IndicatorPowerDeviceProvider * dp) +{ + priv_t * p; + + g_return_if_fail (INDICATOR_IS_POWER_SERVICE (self)); + g_return_if_fail (!dp || INDICATOR_IS_POWER_DEVICE_PROVIDER (dp)); + p = self->priv; + + if (p->device_provider != NULL) + { + g_signal_handlers_disconnect_by_func (p->device_provider, + G_CALLBACK(on_devices_changed), self); + g_clear_object (&p->device_provider); + + dispose_devices (self); + } + + if (dp != NULL) + { + p->device_provider = g_object_ref (dp); + + g_signal_connect_swapped (p->device_provider, "devices-changed", + G_CALLBACK(on_devices_changed), self); + + on_devices_changed (self); + } +} + +IndicatorPowerDevice * +indicator_power_service_choose_primary_device (GList * devices) +{ + IndicatorPowerDevice * primary = NULL; + + if (devices != NULL) + { + GList * tmp; + + tmp = g_list_copy (devices); + tmp = g_list_sort (tmp, device_compare_func); + primary = g_object_ref (tmp->data); + + g_list_free (tmp); + } + + return primary; +} diff --git a/src/service.h b/src/service.h new file mode 100644 index 0000000..77cc362 --- /dev/null +++ b/src/service.h @@ -0,0 +1,79 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#ifndef __INDICATOR_POWER_SERVICE_H__ +#define __INDICATOR_POWER_SERVICE_H__ + +#include +#include + +#include "device-provider.h" + +G_BEGIN_DECLS + +/* standard GObject macros */ +#define INDICATOR_POWER_SERVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_POWER_SERVICE, IndicatorPowerService)) +#define INDICATOR_TYPE_POWER_SERVICE (indicator_power_service_get_type()) +#define INDICATOR_IS_POWER_SERVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_POWER_SERVICE)) + +typedef struct _IndicatorPowerService IndicatorPowerService; +typedef struct _IndicatorPowerServiceClass IndicatorPowerServiceClass; +typedef struct _IndicatorPowerServicePrivate IndicatorPowerServicePrivate; + +/* signal keys */ +#define INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST "name-lost" + +/** + * The Indicator Power Service. + */ +struct _IndicatorPowerService +{ + /*< private >*/ + GObject parent; + IndicatorPowerServicePrivate * priv; +}; + +struct _IndicatorPowerServiceClass +{ + GObjectClass parent_class; + + /* signals */ + + void (* name_lost)(IndicatorPowerService * self); +}; + +/*** +**** +***/ + +GType indicator_power_service_get_type (void); + +IndicatorPowerService * indicator_power_service_new (gboolean replace, + IndicatorPowerDeviceProvider * provider); + +void indicator_power_service_set_device_provider (IndicatorPowerService * self, + IndicatorPowerDeviceProvider * provider); + +IndicatorPowerDevice * indicator_power_service_choose_primary_device (GList * devices); + + + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SERVICE_H__ */ -- cgit v1.2.3 From 997a1091d46410d65fa8a3fdf7c907e1dc8d0707 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:09:29 -0500 Subject: remove the old IndicatorObject code --- src/indicator-power.c | 663 -------------------------------------------------- src/indicator-power.h | 60 ----- 2 files changed, 723 deletions(-) delete mode 100644 src/indicator-power.c delete mode 100644 src/indicator-power.h diff --git a/src/indicator-power.c b/src/indicator-power.c deleted file mode 100644 index 729c7cf..0000000 --- a/src/indicator-power.c +++ /dev/null @@ -1,663 +0,0 @@ -/* -An indicator to power related information in the menubar. - -Copyright 2011 Canonical Ltd. - -Authors: - Javier Jardon - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 . -*/ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -/* GStuff */ -#include -#include -#include - -#include "dbus-listener.h" -#include "device.h" -#include "indicator-power.h" - -#define ICON_POLICY_KEY "icon-policy" - -#define DEFAULT_ICON "gpm-battery-missing" - -enum { - POWER_INDICATOR_ICON_POLICY_PRESENT, - POWER_INDICATOR_ICON_POLICY_CHARGE, - POWER_INDICATOR_ICON_POLICY_NEVER -}; - -struct _IndicatorPowerPrivate -{ - GtkMenu *menu; - - GtkLabel *label; - GtkImage *status_image; - gchar *accessible_desc; - - IndicatorPowerDbusListener * dbus_listener; - - GSList * devices; - IndicatorPowerDevice * device; - - GSettings *settings; -}; - - -/* LCOV_EXCL_START */ -INDICATOR_SET_VERSION -INDICATOR_SET_TYPE (INDICATOR_POWER_TYPE) -/* LCOV_EXCL_STOP */ - -/* Prototypes */ -static void indicator_power_dispose (GObject *object); -static void indicator_power_finalize (GObject *object); - -static GtkLabel* get_label (IndicatorObject * io); -static GtkImage* get_image (IndicatorObject * io); -static GtkMenu* get_menu (IndicatorObject * io); -static const gchar* get_accessible_desc (IndicatorObject * io); -static const gchar* get_name_hint (IndicatorObject * io); - -static void update_visibility (IndicatorPower * self); -static gboolean should_be_visible (IndicatorPower * self); - -static void on_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); - -/* -static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data); -*/ - -/* LCOV_EXCL_START */ -G_DEFINE_TYPE (IndicatorPower, indicator_power, INDICATOR_OBJECT_TYPE); -/* LCOV_EXCL_STOP */ - -static void -indicator_power_class_init (IndicatorPowerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (IndicatorPowerPrivate)); - - object_class->dispose = indicator_power_dispose; - object_class->finalize = indicator_power_finalize; - - io_class->get_label = get_label; - io_class->get_image = get_image; - io_class->get_menu = get_menu; - io_class->get_accessible_desc = get_accessible_desc; - io_class->get_name_hint = get_name_hint; -} - -static void -indicator_power_init (IndicatorPower *self) -{ - IndicatorPowerPrivate * priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_POWER_TYPE, IndicatorPowerPrivate); - - priv->menu = GTK_MENU(gtk_menu_new()); - - priv->accessible_desc = NULL; - - priv->dbus_listener = g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL); - g_signal_connect_swapped (priv->dbus_listener, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, - G_CALLBACK(indicator_power_set_devices), self); - - priv->settings = g_settings_new ("com.canonical.indicator.power"); - g_signal_connect_swapped (priv->settings, "changed::" ICON_POLICY_KEY, - G_CALLBACK(update_visibility), self); - g_object_set (G_OBJECT(self), - INDICATOR_OBJECT_DEFAULT_VISIBILITY, FALSE, - NULL); - - g_signal_connect (INDICATOR_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, - G_CALLBACK(on_entry_added), NULL); - - self->priv = priv; -} - -static void -dispose_devices (IndicatorPower * self) -{ - IndicatorPowerPrivate * priv = self->priv; - - g_clear_object (&priv->device); - g_slist_free_full (priv->devices, g_object_unref); - priv->devices = NULL; -} -static void -indicator_power_dispose (GObject *object) -{ - IndicatorPower *self = INDICATOR_POWER(object); - IndicatorPowerPrivate * priv = self->priv; - - dispose_devices (self); - - g_clear_object (&priv->label); - g_clear_object (&priv->status_image); - g_clear_object (&priv->dbus_listener); - g_clear_object (&priv->settings); - - G_OBJECT_CLASS (indicator_power_parent_class)->dispose (object); -} - -static void -indicator_power_finalize (GObject *object) -{ - IndicatorPower *self = INDICATOR_POWER(object); - IndicatorPowerPrivate * priv = self->priv; - - g_free (priv->accessible_desc); - - G_OBJECT_CLASS (indicator_power_parent_class)->finalize (object); -} - -/*** -**** -***/ - -static void -spawn_command_line_async (const char * command) -{ - GError * err = NULL; - if (!g_spawn_command_line_async (command, &err)) - g_warning ("Couldn't execute command \"%s\": %s", command, err->message); - g_clear_error (&err); -} - -static void -option_toggled_cb (GtkCheckMenuItem *item, IndicatorPower * self) -{ - gtk_widget_set_visible (GTK_WIDGET (self->priv->label), - gtk_check_menu_item_get_active(item)); -} - -/* ensure that the entry is using self's accessible description */ -static void -refresh_entry_accessible_desc (IndicatorPower * self, IndicatorObjectEntry * entry) -{ - const char * newval = self->priv->accessible_desc; - - if (entry->accessible_desc != newval) - { - g_debug ("%s: setting entry %p accessible description to '%s'", G_STRFUNC, entry, newval); - entry->accessible_desc = newval; - g_signal_emit (self, INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, 0, entry); - } -} - -static void -on_entry_added (IndicatorObject * io, - IndicatorObjectEntry * entry, - gpointer user_data G_GNUC_UNUSED) -{ - refresh_entry_accessible_desc (INDICATOR_POWER(io), entry); -} - -static void -set_accessible_desc (IndicatorPower *self, const gchar *desc) -{ - g_debug ("%s: setting accessible description to '%s'", G_STRFUNC, desc); - - if (desc && *desc) - { - /* update our copy of the string */ - char * oldval = self->priv->accessible_desc; - self->priv->accessible_desc = g_strdup (desc); - - /* ensure that the entries are using self's accessible description */ - GList * l; - GList * entries = indicator_object_get_entries(INDICATOR_OBJECT(self)); - for (l=entries; l!=NULL; l=l->next) - refresh_entry_accessible_desc (self, l->data); - - /* cleanup */ - g_list_free (entries); - g_free (oldval); - } -} - -static gboolean -menu_add_device (GtkMenu * menu, const IndicatorPowerDevice * device) -{ - gboolean added = FALSE; - const UpDeviceKind kind = indicator_power_device_get_kind (device); - - if (kind != UP_DEVICE_KIND_LINE_POWER) - { - GtkWidget *icon; - GtkWidget *item; - GtkWidget *details_label; - GtkWidget *grid; - GIcon *device_gicon; - gchar *short_details = NULL; - gchar *details = NULL; - gchar *accessible_name = NULL; - AtkObject *atk_object; - - /* Process the data */ - device_gicon = indicator_power_device_get_gicon (device); - icon = gtk_image_new_from_gicon (device_gicon, GTK_ICON_SIZE_SMALL_TOOLBAR); - g_clear_object (&device_gicon); - - indicator_power_device_get_time_details (device, &short_details, &details, &accessible_name); - - /* Create menu item */ - item = gtk_image_menu_item_new (); - atk_object = gtk_widget_get_accessible(item); - if (atk_object != NULL) - atk_object_set_name (atk_object, accessible_name); - - grid = gtk_grid_new (); - gtk_grid_set_column_spacing (GTK_GRID (grid), 6); - gtk_grid_attach (GTK_GRID (grid), icon, 0, 0, 1, 1); - details_label = gtk_label_new (details); - gtk_grid_attach_next_to (GTK_GRID (grid), details_label, icon, GTK_POS_RIGHT, 1, 1); - gtk_container_add (GTK_CONTAINER (item), grid); - gtk_widget_show (grid); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - added = TRUE; - - g_signal_connect_swapped (G_OBJECT (item), "activate", - G_CALLBACK (spawn_command_line_async), "gnome-power-statistics"); - - g_free (short_details); - g_free (details); - g_free (accessible_name); - } - - return added; -} - -static gsize -menu_add_devices (GtkMenu * menu, GSList * devices) -{ - GSList * l; - gsize n_added = 0; - - for (l=devices; l!=NULL; l=l->next) - if (menu_add_device (menu, l->data)) - ++n_added; - - return n_added; -} - -static gboolean -get_greeter_mode (void) -{ - const gchar *var; - var = g_getenv("INDICATOR_GREETER_MODE"); - return (g_strcmp0(var, "1") == 0); -} - -static void -build_menu (IndicatorPower *self) -{ - GtkWidget *item; - GtkWidget *image; - GList *children; - gsize n_devices = 0; - IndicatorPowerPrivate * priv = self->priv; - - /* remove the existing menuitems */ - children = gtk_container_get_children (GTK_CONTAINER (priv->menu)); - g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL); - g_list_free (children); - - /* devices */ - n_devices = menu_add_devices (priv->menu, priv->devices); - - if (!get_greeter_mode ()) { - /* only do the separator if we have at least one device */ - if (n_devices != 0) - { - item = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); - } - - /* options */ - item = gtk_check_menu_item_new_with_label (_("Show Time in Menu Bar")); - g_signal_connect (item, "toggled", G_CALLBACK(option_toggled_cb), self); - g_settings_bind (priv->settings, "show-time", item, "active", G_SETTINGS_BIND_DEFAULT); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); - - /* preferences */ - item = gtk_image_menu_item_new_with_label (_("Power Settings…")); - image = gtk_image_new_from_icon_name (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - g_signal_connect_swapped (G_OBJECT (item), "activate", - G_CALLBACK (spawn_command_line_async), "gnome-control-center power"); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); - } - - /* show the menu */ - gtk_widget_show_all (GTK_WIDGET (priv->menu)); -} - -/* the higher the weight, the more interesting the device */ -static int -get_device_kind_weight (const IndicatorPowerDevice * device) -{ - UpDeviceKind kind; - static gboolean initialized = FALSE; - static int weights[UP_DEVICE_KIND_LAST]; - - kind = indicator_power_device_get_kind (device); - g_return_val_if_fail (0<=kind && kind b_time ? -1 : 1; - else - ret = a_percentage < b_percentage ? -1 : 1; - } - } - - if (!ret) /* neither device is charging nor discharging... */ - { - const int weight_a = get_device_kind_weight (a); - const int weight_b = get_device_kind_weight (b); - - if (weight_a > weight_b) - { - ret = -1; - } - else if (weight_a < weight_b) - { - ret = 1; - } - } - - if (!ret) - ret = a_state - b_state; - - return ret; -} - -IndicatorPowerDevice * -indicator_power_choose_primary_device (GSList * devices) -{ - IndicatorPowerDevice * primary = NULL; - - if (devices != NULL) - { - GSList * tmp; - - tmp = g_slist_copy (devices); - tmp = g_slist_sort (tmp, device_compare_func); - primary = g_object_ref (tmp->data); - - g_slist_free (tmp); - } - - return primary; -} - -static void -put_primary_device (IndicatorPower *self, IndicatorPowerDevice *device) -{ - IndicatorPowerPrivate * priv = self->priv; - - /* set icon */ - GIcon * device_gicon = indicator_power_device_get_gicon (device); - gtk_image_set_from_gicon (priv->status_image, device_gicon, GTK_ICON_SIZE_LARGE_TOOLBAR); - g_clear_object (&device_gicon); - gtk_widget_show (GTK_WIDGET (priv->status_image)); - - /* get the description */ - gchar * short_details; - gchar * details; - gchar * accessible_name; - indicator_power_device_get_time_details (device, &short_details, &details, &accessible_name); - gtk_label_set_label (GTK_LABEL (priv->label), short_details); - set_accessible_desc (self, accessible_name); - g_free (accessible_name); - g_free (details); - g_free (short_details); -} - -void -indicator_power_set_devices (IndicatorPower * self, GSList * devices) -{ - /* LCOV_EXCL_START */ - g_return_if_fail (IS_INDICATOR_POWER(self)); - /* LCOV_EXCL_STOP */ - - IndicatorPowerPrivate * priv = self->priv; - - /* update our devices & primary device */ - g_slist_foreach (devices, (GFunc)g_object_ref, NULL); - dispose_devices (self); - priv->devices = g_slist_copy (devices); - priv->device = indicator_power_choose_primary_device (devices); - - /* and our menus/visibility from the new device list */ - if (priv->device != NULL) - put_primary_device (self, priv->device); - else - g_message ("Couldn't find primary device"); - build_menu (self); - update_visibility (self); -} - -static void -update_visibility (IndicatorPower * self) -{ - indicator_object_set_visible (INDICATOR_OBJECT (self), - should_be_visible (self)); -} - - -/* Grabs the label. Creates it if it doesn't - exist already */ -static GtkLabel * -get_label (IndicatorObject *io) -{ - IndicatorPower *self = INDICATOR_POWER (io); - IndicatorPowerPrivate * priv = self->priv; - - if (priv->label == NULL) - { - /* Create the label if it doesn't exist already */ - priv->label = GTK_LABEL (gtk_label_new ("")); - g_object_ref_sink (priv->label); - gtk_widget_set_visible (GTK_WIDGET (priv->label), FALSE); - } - - return priv->label; -} - -static GtkImage * -get_image (IndicatorObject *io) -{ - GIcon *gicon; - IndicatorPower *self = INDICATOR_POWER (io); - IndicatorPowerPrivate * priv = self->priv; - - if (priv->status_image == NULL) - { - /* Will create the status icon if it doesn't exist already */ - gicon = g_themed_icon_new (DEFAULT_ICON); - priv->status_image = GTK_IMAGE (gtk_image_new_from_gicon (gicon, - GTK_ICON_SIZE_LARGE_TOOLBAR)); - g_object_ref_sink (priv->status_image); - g_object_unref (gicon); - } - - return priv->status_image; -} - -static GtkMenu * -get_menu (IndicatorObject *io) -{ - IndicatorPower *self = INDICATOR_POWER (io); - - build_menu (self); - - return GTK_MENU (self->priv->menu); -} - -static const gchar * -get_accessible_desc (IndicatorObject *io) -{ - IndicatorPower *self = INDICATOR_POWER (io); - - return self->priv->accessible_desc; -} - -static const gchar * -get_name_hint (IndicatorObject *io) -{ - return PACKAGE_NAME; -} - -/*** -**** -***/ - -static void -count_batteries (GSList * devices, int *total, int *inuse) -{ - GSList * l; - - for (l=devices; l!=NULL; l=l->next) - { - const IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); - - if (indicator_power_device_get_kind(device) == UP_DEVICE_KIND_BATTERY || - indicator_power_device_get_kind(device) == UP_DEVICE_KIND_UPS) - { - ++*total; - - const UpDeviceState state = indicator_power_device_get_state (device); - if ((state == UP_DEVICE_STATE_CHARGING) || (state == UP_DEVICE_STATE_DISCHARGING)) - ++*inuse; - } - } - - g_debug("count_batteries found %d batteries (%d are charging/discharging)", *total, *inuse); -} - -static gboolean -should_be_visible (IndicatorPower * self) -{ - gboolean visible = TRUE; - IndicatorPowerPrivate * priv = self->priv; - - const int icon_policy = g_settings_get_enum (priv->settings, ICON_POLICY_KEY); - - g_debug ("icon_policy is: %d (present==0, charge==1, never==2)", icon_policy); - - if (icon_policy == POWER_INDICATOR_ICON_POLICY_NEVER) - { - visible = FALSE; - } - else - { - int batteries=0, inuse=0; - count_batteries (priv->devices, &batteries, &inuse); - - if (icon_policy == POWER_INDICATOR_ICON_POLICY_PRESENT) - { - visible = batteries > 0; - } - else if (icon_policy == POWER_INDICATOR_ICON_POLICY_CHARGE) - { - visible = inuse > 0; - } - } - - g_debug ("should_be_visible: %s", visible?"yes":"no"); - return visible; -} diff --git a/src/indicator-power.h b/src/indicator-power.h deleted file mode 100644 index 34d0d0e..0000000 --- a/src/indicator-power.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -An indicator to power related information in the menubar. - -Copyright 2011 Canonical Ltd. - -Authors: - Javier Jardon - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 . -*/ - -/* Gtk required */ -#include - -/* parent class */ -#include -#include - -G_BEGIN_DECLS - -#define INDICATOR_POWER_TYPE (indicator_power_get_type ()) -#define INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_TYPE, IndicatorPower)) -#define INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_TYPE, IndicatorPowerClass)) -#define IS_INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_TYPE)) -#define IS_INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_TYPE)) -#define INDICATOR_POWER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_TYPE, IndicatorPowerClass)) - -typedef struct _IndicatorPower IndicatorPower; -typedef struct _IndicatorPowerClass IndicatorPowerClass; -typedef struct _IndicatorPowerPrivate IndicatorPowerPrivate; - -struct _IndicatorPowerClass -{ - IndicatorObjectClass parent_class; -}; - -struct _IndicatorPower -{ - IndicatorObject parent_instance; - IndicatorPowerPrivate * priv; -}; - -GType indicator_power_get_type (void) G_GNUC_CONST; - -void indicator_power_set_devices (IndicatorPower * power, - GSList * devices); - -IndicatorPowerDevice* indicator_power_choose_primary_device (GSList * devices); - -G_END_DECLS -- cgit v1.2.3 From cbbf63caf72e04919c4066902ff5008b3874047c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:10:06 -0500 Subject: add a main() wrapper to create a service and pass a device-provider-upower to it --- src/main.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main.c diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7bb6b92 --- /dev/null +++ b/src/main.c @@ -0,0 +1,101 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#include "config.h" + +#include +#include /* exit() */ + +#include +#include + +#include "device.h" +#include "device-provider-upower.h" +#include "service.h" + +/*** +**** +***/ + +static gboolean replace = FALSE; + +static void +parse_command_line (int * argc, char *** argv) +{ + GError * error; + GOptionContext * option_context; + + static GOptionEntry entries[] = + { + { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "Replace the currently-running service", NULL }, + { NULL } + }; + + error = NULL; + option_context = g_option_context_new ("- indicator-power service"); + g_option_context_add_main_entries (option_context, entries, GETTEXT_PACKAGE); + if (!g_option_context_parse (option_context, argc, argv, &error)) + { + g_print ("option parsing failed: %s\n", error->message); + g_error_free (error); + exit (EXIT_FAILURE); + } + + g_option_context_free (option_context); +} + +/*** +**** +***/ + +static void +on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) +{ + g_message ("exiting: service couldn't acquire or lost ownership of busname"); + g_main_loop_quit ((GMainLoop*)loop); +} + +int +main (int argc, char ** argv) +{ + GMainLoop * loop; + IndicatorPowerService * service; + IndicatorPowerDeviceProvider * device_provider; + + /* boilerplate i18n */ + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); + + parse_command_line (&argc, &argv); + + /* run */ + device_provider = indicator_power_device_provider_upower_new (); + service = indicator_power_service_new (replace, device_provider); + loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST, + G_CALLBACK(on_name_lost), loop); + g_main_loop_run (loop); + + /* cleanup */ + g_clear_object (&device_provider); + g_clear_object (&service); + g_main_loop_unref (loop); + return 0; +} -- cgit v1.2.3 From f5c93cdcc7f2728560ea9aa27df17d85b74a28c1 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:16:19 -0500 Subject: explicitly use gio; remove unused glib-upower.h calls --- src/device.c | 25 +++++++++++++++++++++++-- src/device.h | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/device.c b/src/device.c index d028ab7..02c9e65 100644 --- a/src/device.c +++ b/src/device.c @@ -26,6 +26,7 @@ License along with this library. If not, see #endif #include +#include #include "device.h" @@ -301,6 +302,26 @@ get_device_icon_index (gdouble percentage) return "000"; } +static const char * +device_kind_to_string (UpDeviceKind kind) +{ + switch (kind) + { + case UP_DEVICE_KIND_LINE_POWER: return "line-power"; + case UP_DEVICE_KIND_BATTERY: return "battery"; + case UP_DEVICE_KIND_UPS: return "ups"; + case UP_DEVICE_KIND_MONITOR: return "monitor"; + case UP_DEVICE_KIND_MOUSE: return "mouse"; + case UP_DEVICE_KIND_KEYBOARD: return "keyboard"; + case UP_DEVICE_KIND_PDA: return "pda"; + case UP_DEVICE_KIND_PHONE: return "phone"; + case UP_DEVICE_KIND_MEDIA_PLAYER: return "media-player"; + case UP_DEVICE_KIND_TABLET: return "tablet"; + case UP_DEVICE_KIND_COMPUTER: return "computer"; + default: return "unknown"; + } +} + /** indicator_power_device_get_icon_names: @device: #IndicatorPowerDevice from which to generate the icon names @@ -334,7 +355,7 @@ indicator_power_device_get_icon_names (const IndicatorPowerDevice * device) gdouble percentage = indicator_power_device_get_percentage (device); const UpDeviceKind kind = indicator_power_device_get_kind (device); const UpDeviceState state = indicator_power_device_get_state (device); - const gchar * kind_str = up_device_kind_to_string (kind); + const gchar * kind_str = device_kind_to_string (kind); GPtrArray * names = g_ptr_array_new (); @@ -534,7 +555,7 @@ device_kind_to_localised_string (UpDeviceKind kind) break; default: g_warning ("enum unrecognised: %i", kind); - text = up_device_kind_to_string (kind); + text = device_kind_to_string (kind); } return text; diff --git a/src/device.h b/src/device.h index 3f7bbee..ffbb5da 100644 --- a/src/device.h +++ b/src/device.h @@ -25,7 +25,6 @@ License along with this library. If not, see #define __INDICATOR_POWER_DEVICE_H__ #include -#include G_BEGIN_DECLS @@ -46,6 +45,38 @@ typedef struct _IndicatorPowerDevicePrivate IndicatorPowerDevicePrivate; #define INDICATOR_POWER_DEVICE_PERCENTAGE "percentage" #define INDICATOR_POWER_DEVICE_TIME "time" +typedef enum +{ + UP_DEVICE_KIND_UNKNOWN, + UP_DEVICE_KIND_LINE_POWER, + UP_DEVICE_KIND_BATTERY, + UP_DEVICE_KIND_UPS, + UP_DEVICE_KIND_MONITOR, + UP_DEVICE_KIND_MOUSE, + UP_DEVICE_KIND_KEYBOARD, + UP_DEVICE_KIND_PDA, + UP_DEVICE_KIND_PHONE, + UP_DEVICE_KIND_MEDIA_PLAYER, + UP_DEVICE_KIND_TABLET, + UP_DEVICE_KIND_COMPUTER, + UP_DEVICE_KIND_LAST +} +UpDeviceKind; + +typedef enum +{ + UP_DEVICE_STATE_UNKNOWN, + UP_DEVICE_STATE_CHARGING, + UP_DEVICE_STATE_DISCHARGING, + UP_DEVICE_STATE_EMPTY, + UP_DEVICE_STATE_FULLY_CHARGED, + UP_DEVICE_STATE_PENDING_CHARGE, + UP_DEVICE_STATE_PENDING_DISCHARGE, + UP_DEVICE_STATE_LAST +} +UpDeviceState; + + /** * IndicatorPowerDeviceClass: * @parent_class: #GObjectClass -- cgit v1.2.3 From 1d8adeb255e0499ba27508be0530827fe0c052db Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:18:11 -0500 Subject: add power.indicator --- data/power.indicator | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 data/power.indicator diff --git a/data/power.indicator b/data/power.indicator new file mode 100644 index 0000000..1ebc075 --- /dev/null +++ b/data/power.indicator @@ -0,0 +1,9 @@ +[Indicator Service] +Name=indicator-power +ObjectPath=/com/canonical/indicator/power + +[desktop] +ObjectPath=/com/canonical/indicator/power/desktop + +[greeter] +ObjectPath=/com/canonical/indicator/power/greeter -- cgit v1.2.3 From b8f5e0707f454ff8d9e87c65aa058847f587be34 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:31:41 -0500 Subject: update build rules: remove now-unneeded build dependencies for libindicator, gtk, gnome-settings-daemon-dev, libupower-glib, libdbus-1-dev --- configure.ac | 23 ++++++++++------------- debian/control | 6 ------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 0601c16..c6cc8e0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,9 @@ AC_INIT([indicator-power], - [12.10.6], + [13.10.0], [http://bugs.launchpad.net/indicator-power], [indicator-power], [http://launchpad.net/indicator-power]) +AC_COPYRIGHT([Copyright 2011-2013 Canonical]) AC_PREREQ([2.64]) @@ -29,25 +30,20 @@ LT_INIT ########################### # Dependencies ########################### + GLIB_REQUIRED_VERSION=2.35.4 GIO_REQUIRED_VERSION=2.26 -GTK_REQUIRED_VERSION=3.0 -INDICATOR_REQUIRED_VERSION=0.3.90 -UPOWER_REQUIRED_VERSION=0.9.5 +GIO_UNIX_REQUIRED_VERSION=2.26 GSD_REQUIRED_VERSION=3.1.4 -PKG_CHECK_MODULES([UPOWER],[upower-glib >= UPOWER_REQUIRED_VERSION]) - -PKG_CHECK_MODULES([INDICATOR],[glib-2.0 >= $GLIB_REQUIRED_VERSION - gio-2.0 >= $GIO_REQUIRED_VERSION - gtk+-3.0 >= $GTK_REQUIRED_VERSION - indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION -]) -PKG_CHECK_MODULES([GSD],[gnome-settings-daemon >= $GSD_REQUIRED_VERSION]) +PKG_CHECK_MODULES([SERVICE_DEPS],[glib-2.0 >= $GLIB_REQUIRED_VERSION + gio-2.0 >= $GIO_REQUIRED_VERSION + gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION]) ########################### # GSETTINGS ########################### + GLIB_GSETTINGS ########################### @@ -126,13 +122,14 @@ AC_DEFUN([AC_DEFINE_PATH], [ # Internationalization ########################### -IT_PROG_INTLTOOL([0.41.0]) +IT_PROG_INTLTOOL([0.50.0]) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.17]) AC_SUBST([GETTEXT_PACKAGE],[${PACKAGE_TARNAME}]) AC_DEFINE([GETTEXT_PACKAGE],[PACKAGE_TARNAME],[Define to the gettext package name.]) +AC_DEFINE_PATH([GNOMELOCALEDIR],"${datadir}/locale",[locale directory]) ########################### # Files diff --git a/debian/control b/debian/control index e9ebbd2..2be3f6f 100644 --- a/debian/control +++ b/debian/control @@ -8,12 +8,7 @@ Build-Depends: debhelper (>= 9), intltool, libxorg-gtest-dev, libgtest-dev, - libgtk-3-dev, libglib2.0-dev (>= 2.35.4), - libindicator3-dev (>= 0.3.90), - libupower-glib-dev (>= 0.9.5), - gnome-settings-daemon-dev (>= 3.1.4), - libdbus-1-dev, Standards-Version: 3.9.2 Homepage: https://launchpad.net/indicator-power # If you aren't a member of ~indicator-applet-developers but need to upload @@ -28,7 +23,6 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, upower, gnome-control-center (>= 3.1), - gnome-settings-daemon, Recommends: indicator-applet (>= 0.2) | indicator-renderer, Description: Indicator showing power state. This indicator displays current power management information and gives -- cgit v1.2.3 From 1ad51b4ec12a5dc7a270069b27a7bcd8d60da2f0 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:32:29 -0500 Subject: update indicator-power build rules to reflect the changes in source code and in dependencies --- src/Makefile.am | 122 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index b2cf3df..2aff220 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,36 +1,90 @@ +BUILT_SOURCES = +EXTRA_DIST = CLEANFILES = -ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} - -################### -# Indicator Stuff -################### - -powerlibdir = $(INDICATORDIR) -powerlib_LTLIBRARIES = libpower.la - -libpower_la_SOURCES = \ - dbus-listener.c \ - dbus-listener.h \ - device.c \ - device.h \ - indicator-power.h \ - indicator-power.c - -CLEANFILES += .libs/*.gcda .libs/*.gcno *.gcda *.gcno - -libpower_la_CFLAGS = \ - $(UPOWER_CFLAGS) \ - $(INDICATOR_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - -Wall -Werror \ - -DG_LOG_DOMAIN=\"Indicator-Power\" - -libpower_la_LIBADD = \ - $(UPOWER_LIBS) \ - $(INDICATOR_LIBS) - -libpower_la_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - -module \ - -avoid-version + +SHARED_CFLAGS = \ + -Wall -Werror \ + $(SERVICE_DEPS_CFLAGS) \ + -DG_LOG_DOMAIN=\"Indicator-Power\" + +### +### + +upower_dbus_sources = \ + dbus-upower.c \ + dbus-upower.h + +$(upower_dbus_sources): org.freedesktop.UPower.xml + $(AM_V_GEN) gdbus-codegen \ + --c-namespace Dbus \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-upower \ + $^ + +BUILT_SOURCES += $(upower_dbus_sources) +CLEANFILES += $(upower_dbus_sources) +EXTRA_DIST += org.freedesktop.UPower.xml + +### +### + +upower_device_dbus_sources = \ + dbus-upower-device.c \ + dbus-upower-device.h + +$(upower_device_dbus_sources): org.freedesktop.UPower.Device.xml + $(AM_V_GEN) gdbus-codegen \ + --c-namespace Dbus \ + --interface-prefix org.freedesktop.UPower \ + --generate-c-code dbus-upower-device \ + $^ + +BUILT_SOURCES += $(upower_device_dbus_sources) +CLEANFILES += $(upower_device_dbus_sources) +EXTRA_DIST += org.freedesktop.UPower.Device.xml + +### +### +### + +noinst_LIBRARIES = libindicatorpower-upower.a libindicatorpower-service.a + +libindicatorpower_upower_a_SOURCES = \ + $(upower_dbus_sources) \ + $(upower_device_dbus_sources) \ + device-provider-upower.c \ + device-provider-upower.h + +libindicatorpower_upower_a_CFLAGS = $(SHARED_CFLAGS) -Wextra -Wno-unused-parameter + +libindicatorpower_service_a_SOURCES = \ + device-provider.c \ + device-provider.h \ + device.c \ + device.h \ + service.c \ + service.h + +libindicatorpower_service_a_CFLAGS = $(SHARED_CFLAGS) + +### +### +### + +libexec_PROGRAMS = indicator-power-service + +indicator_power_service_SOURCES = main.c + +indicator_power_service_CFLAGS = \ + $(SHARED_CFLAGS) \ + -Wextra -Wno-missing-field-initializers + +indicator_power_service_LDADD = \ + libindicatorpower-upower.a \ + libindicatorpower-service.a \ + $(SERVICE_DEPS_LIBS) + +indicator_power_service_LDFLAGS = \ + $(COVERAGE_LDFLAGS) + -- cgit v1.2.3 From 545b34108a6752c6a6554f4bda1cafda79e8aabe Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:32:58 -0500 Subject: first steps at fixing the tests that broke during GMenuification --- tests/Makefile.am | 8 ++------ tests/test-device.cc | 7 ++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index a194505..d8e329e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,17 +23,13 @@ AM_CXXFLAGS = $(GTEST_CXXFLAGS) ### TEST_LIBS = \ - $(top_builddir)/src/.libs/libpower.a \ - $(INDICATOR_LIBS) \ - $(UPOWER_LIBS) \ - $(COVERAGE_LDFLAGS) \ + $(COVERAGE_LDFLAGS) \ $(XORG_GTEST_LDFLAGS) \ libgtest.a TEST_CPPFLAGS = \ $(AM_CPPFLAGS) \ - $(UPOWER_CFLAGS) \ - $(INDICATOR_CFLAGS) + $(SERVICE_DEPS_CFLAGS) BUILT_SOURCES += gschemas.compiled CLEANFILES += gschemas.compiled diff --git a/tests/test-device.cc b/tests/test-device.cc index ab329f1..9c48699 100644 --- a/tests/test-device.cc +++ b/tests/test-device.cc @@ -17,9 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include #include "device.h" -#include "indicator-power.h" +#include "service.h" class DeviceTest : public ::testing::Test { @@ -597,11 +598,11 @@ TEST_F(DeviceTest, ChoosePrimary) INDICATOR_POWER_DEVICE_TIME, guint64(tests[j].time), INDICATOR_POWER_DEVICE_PERCENTAGE, tests[j].percentage, NULL); - ASSERT_EQ (a, indicator_power_choose_primary_device(device_list)); + ASSERT_EQ (a, indicator_power_service_choose_primary_device(device_list)); /* reverse the list to check that list order doesn't matter */ device_list = g_slist_reverse (device_list); - ASSERT_EQ (a, indicator_power_choose_primary_device(device_list)); + ASSERT_EQ (a, indicator_power_service_choose_primary_device(device_list)); } } -- cgit v1.2.3 From 37051c1fa5a9c4f805ec717bebd185334eb46888 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 16 Jun 2013 23:33:30 -0500 Subject: add a short-term TODO file --- TODO | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..54b363f --- /dev/null +++ b/TODO @@ -0,0 +1,7 @@ +Short Term + - look for leaks by leaving running in valgrind + - fix broken tests + - install .indicator file + +Longer Term + - better coverage -- cgit v1.2.3 From a4d5e56e8022cf5e3b22aa8fa2ec5930c2c5c429 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 08:30:39 -0500 Subject: copyediting: group common functions together, fix line wrap, better commenting --- src/service.c | 147 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 72 insertions(+), 75 deletions(-) diff --git a/src/service.c b/src/service.c index 5aabefc..49fc4d7 100644 --- a/src/service.c +++ b/src/service.c @@ -50,10 +50,10 @@ enum PROP_0, PROP_REPLACE, PROP_DEVICE_PROVIDER, - PROP_LAST + LAST_PROP }; -static GParamSpec * properties[PROP_LAST]; +static GParamSpec * properties[LAST_PROP]; enum { @@ -119,30 +119,6 @@ struct _IndicatorPowerServicePrivate typedef IndicatorPowerServicePrivate priv_t; -/*** -**** -***/ - -static void rebuild_now (IndicatorPowerService * self, guint section); - -static inline void -rebuild_header_now (IndicatorPowerService * self) -{ - rebuild_now (self, SECTION_HEADER); -} - -static inline void -rebuild_devices_section_now (IndicatorPowerService * self) -{ - rebuild_now (self, SECTION_DEVICES); -} - -static inline void -rebuild_settings_section_now (IndicatorPowerService * self) -{ - rebuild_now (self, SECTION_SETTINGS); -} - /*** **** **** DEVICES @@ -263,32 +239,6 @@ device_compare_func (gconstpointer ga, gconstpointer gb) return ret; } -static void -dispose_devices (IndicatorPowerService * self) -{ - priv_t * p = self->priv; - - g_clear_object (&p->primary_device); - g_list_free_full (p->devices, g_object_unref); - p->devices = NULL; -} - -static void -on_devices_changed (IndicatorPowerService * self) -{ - priv_t * p = self->priv; - - /* update the device list */ - g_list_free_full (p->devices, (GDestroyNotify)g_object_unref); - p->devices = indicator_power_device_provider_get_devices (p->device_provider); - - /* update the primary device */ - g_clear_object (&p->primary_device); - p->primary_device = indicator_power_service_choose_primary_device (p->devices); - - rebuild_now (self, SECTION_HEADER | SECTION_DEVICES); -} - /*** **** **** HEADER SECTION @@ -490,6 +440,7 @@ create_settings_section (IndicatorPowerService * self G_GNUC_UNUSED) /*** **** +**** SECTION REBUILDING **** ***/ @@ -533,6 +484,24 @@ rebuild_now (IndicatorPowerService * self, guint sections) } } +static inline void +rebuild_header_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_HEADER); +} + +static inline void +rebuild_devices_section_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_DEVICES); +} + +static inline void +rebuild_settings_section_now (IndicatorPowerService * self) +{ + rebuild_now (self, SECTION_SETTINGS); +} + static void create_menu (IndicatorPowerService * self, int profile) { @@ -617,6 +586,8 @@ on_statistics_activated (GSimpleAction * a G_GNUC_UNUSED, execute_command ("gnome-power-statistics"); } +/* FIXME: use a GBinding to tie the gaction's state and the GSetting together? */ + static void set_show_time_flag (IndicatorPowerService * self, gboolean b) { @@ -638,15 +609,18 @@ set_show_time_flag (IndicatorPowerService * self, gboolean b) static void on_show_time_setting_changed (GSettings * settings, gchar * key, gpointer gself) { - set_show_time_flag (gself, g_settings_get_boolean (settings, key)); + set_show_time_flag (INDICATOR_POWER_SERVICE(gself), + g_settings_get_boolean (settings, key)); } + static void on_show_time_action_state_changed (GAction * action, GParamSpec * pspec G_GNUC_UNUSED, gpointer gself) { GVariant * v = g_action_get_state (action); - set_show_time_flag (gself, g_variant_get_boolean (v)); + set_show_time_flag (INDICATOR_POWER_SERVICE(gself), + g_variant_get_boolean (v)); g_variant_unref (v); } @@ -702,7 +676,7 @@ init_gactions (IndicatorPowerService * self) } /*** -**** GDBus +**** GDBus Name Ownership & Menu / Action Exporting ***/ static void @@ -802,6 +776,26 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); } +/*** +**** Events +***/ + +static void +on_devices_changed (IndicatorPowerService * self) +{ + priv_t * p = self->priv; + + /* update the device list */ + g_list_free_full (p->devices, (GDestroyNotify)g_object_unref); + p->devices = indicator_power_device_provider_get_devices (p->device_provider); + + /* update the primary device */ + g_clear_object (&p->primary_device); + p->primary_device = indicator_power_service_choose_primary_device (p->devices); + + rebuild_now (self, SECTION_HEADER | SECTION_DEVICES); +} + /*** **** GObject virtual functions @@ -814,8 +808,8 @@ my_constructed (GObject * o) IndicatorPowerService * self = INDICATOR_POWER_SERVICE(o); priv_t * p = self->priv; - /* own the name in constructed() instead of init() so that - we'll know the value of the 'replace' property */ + /* own the name here in constructed() instead of init() + so that we know the value of the 'replace' property */ owner_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; if (p->replace) owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; @@ -969,22 +963,21 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) properties[PROP_0] = NULL; - properties[PROP_REPLACE] = g_param_spec_boolean ("replace", - "Replace Service", - "Replace existing service", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - properties[PROP_DEVICE_PROVIDER] = g_param_spec_object ("device-provider", - "Device Provider", - "Source for power devices", - G_TYPE_OBJECT, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST, properties); + properties[PROP_REPLACE] = g_param_spec_boolean ( + "replace", + "Replace Service", + "Replace existing service", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_DEVICE_PROVIDER] = g_param_spec_object ( + "device-provider", + "Device Provider", + "Source for power devices", + G_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, LAST_PROP, properties); } /*** @@ -1016,10 +1009,14 @@ indicator_power_service_set_device_provider (IndicatorPowerService * self, if (p->device_provider != NULL) { g_signal_handlers_disconnect_by_func (p->device_provider, - G_CALLBACK(on_devices_changed), self); + G_CALLBACK(on_devices_changed), + self); g_clear_object (&p->device_provider); - dispose_devices (self); + g_clear_object (&p->primary_device); + + g_list_free_full (p->devices, g_object_unref); + p->devices = NULL; } if (dp != NULL) -- cgit v1.2.3 From 72d74f44b31cefa9d5f4b66d34f9546cb4b40d5a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 11:53:41 -0500 Subject: in device-provider-upower's dispose(), disconnect from our proxy's signal before we unref the proxy --- src/device-provider-upower.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/device-provider-upower.c b/src/device-provider-upower.c index 850717e..7cc8858 100644 --- a/src/device-provider-upower.c +++ b/src/device-provider-upower.c @@ -35,7 +35,7 @@ struct _IndicatorPowerDeviceProviderUPowerPriv { DbusUPower * upower_proxy; - GHashTable * devices; + GHashTable * devices; /* dbus object path --> IndicatorPowerDevice */ GCancellable * cancellable; guint timer; }; @@ -67,7 +67,7 @@ G_DEFINE_TYPE_WITH_CODE ( * triggers a device-removed signal, and also a device-changed as the * battery's state changes to 'discharging'. * - * We use a small timer here to fold upower events into a single + * We use a small timer here to fold multiple upower events into a single * IndicatorPowerDeviceProvider devices-changed signal. */ @@ -111,6 +111,8 @@ on_upower_device_proxy_ready (GObject * o, GAsyncResult * res, gpointer gself) } else { + /* use this proxy's properties to update our own IndicatorPowerDevice */ + IndicatorPowerDevice * device; IndicatorPowerDeviceProviderUPower * self; priv_t * p; @@ -295,8 +297,13 @@ my_dispose (GObject * o) p->timer = 0; } - - g_clear_object (&p->upower_proxy); + + if (p->upower_proxy != NULL) + { + g_signal_handlers_disconnect_by_data (p->upower_proxy, self); + + g_clear_object (&p->upower_proxy); + } g_clear_pointer (&p->devices, g_hash_table_destroy); -- cgit v1.2.3 From aa625b0b86ed15755b0b7cebc7f90da55059e3a6 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 12:00:41 -0500 Subject: tighten the -Wextra screws a little tighter --- src/Makefile.am | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 2aff220..8495233 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,7 @@ EXTRA_DIST = CLEANFILES = SHARED_CFLAGS = \ - -Wall -Werror \ + -Wall -Wextra -Werror \ $(SERVICE_DEPS_CFLAGS) \ -DG_LOG_DOMAIN=\"Indicator-Power\" @@ -55,7 +55,7 @@ libindicatorpower_upower_a_SOURCES = \ device-provider-upower.c \ device-provider-upower.h -libindicatorpower_upower_a_CFLAGS = $(SHARED_CFLAGS) -Wextra -Wno-unused-parameter +libindicatorpower_upower_a_CFLAGS = $(SHARED_CFLAGS) -Wno-unused-parameter libindicatorpower_service_a_SOURCES = \ device-provider.c \ @@ -65,7 +65,7 @@ libindicatorpower_service_a_SOURCES = \ service.c \ service.h -libindicatorpower_service_a_CFLAGS = $(SHARED_CFLAGS) +libindicatorpower_service_a_CFLAGS = $(SHARED_CFLAGS) -Wno-missing-field-initializers ### ### @@ -75,9 +75,7 @@ libexec_PROGRAMS = indicator-power-service indicator_power_service_SOURCES = main.c -indicator_power_service_CFLAGS = \ - $(SHARED_CFLAGS) \ - -Wextra -Wno-missing-field-initializers +indicator_power_service_CFLAGS = $(SHARED_CFLAGS) indicator_power_service_LDADD = \ libindicatorpower-upower.a \ -- cgit v1.2.3 From 9990582a27a15942c6f4183b844cf532e217c788 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 18:01:04 -0500 Subject: remove the gtest-xorg dependency, we're no longer using gui elements in the tests --- configure.ac | 1 - debian/control | 1 - 2 files changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac index c6cc8e0..5e29f36 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,6 @@ AC_ARG_ENABLE([tests], if test "x$enable_tests" != "xno"; then m4_include([m4/gtest.m4]) CHECK_GTEST - CHECK_XORG_GTEST if test "x$enable_tests" = "xauto"; then enable_tests=${have_gtest} elif test "x$enable_tests" = "xyes" && test "x$have_gtest" != "xyes"; then diff --git a/debian/control b/debian/control index 2be3f6f..169665f 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,6 @@ Build-Depends: debhelper (>= 9), dh-autoreconf, autopoint, intltool, - libxorg-gtest-dev, libgtest-dev, libglib2.0-dev (>= 2.35.4), Standards-Version: 3.9.2 -- cgit v1.2.3 From b3a23dc2556cfde8a7d6f4262a21a28a5faafdbe Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 18:01:26 -0500 Subject: update POTFILES.in to reflect the new files in src/ --- po/POTFILES.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 3061414..d7701f4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,3 @@ data/com.canonical.indicator.power.gschema.xml.in src/device.c -src/dbus-listener.c -src/indicator-power.c +src/service.c -- cgit v1.2.3 From bef4229b70139014df071ecba3742e99639dac42 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 17 Jun 2013 18:01:51 -0500 Subject: get test-devices building and passing again. --- tests/Makefile.am | 65 +++++----- tests/test-device.cc | 20 +-- tests/test-indicator.cc | 325 ------------------------------------------------ tests/test-service.cc | 324 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 365 deletions(-) delete mode 100644 tests/test-indicator.cc create mode 100644 tests/test-service.cc diff --git a/tests/Makefile.am b/tests/Makefile.am index d8e329e..5c7d802 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,56 +4,61 @@ BUILT_SOURCES = check_PROGRAMS = ### -### +### tests: stock tests on user-visible strings ### -# stock UMB tests on user-visible strings include $(srcdir)/Makefile.am.strings +### +### gtest library +### + check_LIBRARIES = libgtest.a nodist_libgtest_a_SOURCES = \ - $(GTEST_SOURCE)/gtest-all.cc \ - $(GTEST_SOURCE)/gtest_main.cc + $(GTEST_SOURCE)/src/gtest-all.cc \ + $(GTEST_SOURCE)/src/gtest_main.cc AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I${top_srcdir}/src -Wall -Werror AM_CXXFLAGS = $(GTEST_CXXFLAGS) ### +### tests: indicator-power-device ### -### - -TEST_LIBS = \ - $(COVERAGE_LDFLAGS) \ - $(XORG_GTEST_LDFLAGS) \ - libgtest.a -TEST_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(SERVICE_DEPS_CFLAGS) - -BUILT_SOURCES += gschemas.compiled -CLEANFILES += gschemas.compiled -gschemas.compiled: Makefile - @glib-compile-schemas --targetdir=$(abs_builddir) $(top_builddir)/data +TEST_LIBS = $(COVERAGE_LDFLAGS) libgtest.a -lpthread +TEST_CPPFLAGS = $(SERVICE_DEPS_CFLAGS) $(AM_CPPFLAGS) TESTS += test-device check_PROGRAMS += test-device test_device_SOURCES = test-device.cc -test_device_LDADD = $(TEST_LIBS) -test_device_CPPFLAGS = $(TEST_CPPFLAGS) +test_device_CPPFLAGS = $(TEST_CPPFLAGS) -Wall -Werror -Wextra +test_device_LDADD = \ + $(top_builddir)/src/libindicatorpower-service.a \ + $(SERVICE_DEPS_LIBS) \ + $(TEST_LIBS) + +# (FIXME: incomplete) +# +### +### tests: indicator-power-service +### +# +# build a local copy of the GSettings schemas +#BUILT_SOURCES += gschemas.compiled +#CLEANFILES += gschemas.compiled +#gschemas.compiled: Makefile +# @glib-compile-schemas --targetdir=$(abs_builddir) $(top_builddir)/data +# +#TESTS += test-service +#check_PROGRAMS += test-service +#test_service_SOURCES = test-service.cc +#test_service_LDADD = $(TEST_LIBS) +#test_service_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests/\"" +# #TESTS += test-dbus-listener #check_PROGRAMS += test-dbus-listener #test_dbus_listener_SOURCES = test-dbus-listener.cc #test_dbus_listener_LDADD = $(TEST_LIBS) #test_dbus_listener_CPPFLAGS = $(TEST_CPPFLAGS) - -TESTS += test-indicator -check_PROGRAMS += test-indicator -test_indicator_SOURCES = test-indicator.cc -test_indicator_LDADD = $(TEST_LIBS) -test_indicator_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests/\"" - -### -### -### +# diff --git a/tests/test-device.cc b/tests/test-device.cc index 9c48699..987b201 100644 --- a/tests/test-device.cc +++ b/tests/test-device.cc @@ -30,12 +30,12 @@ class DeviceTest : public ::testing::Test int log_count_ipower_actual; - static void log_count_func (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) + static void log_count_func (const gchar * log_domain G_GNUC_UNUSED, + GLogLevelFlags log_level G_GNUC_UNUSED, + const gchar * message G_GNUC_UNUSED, + gpointer gself) { - reinterpret_cast(user_data)->log_count_ipower_actual++; + reinterpret_cast(gself)->log_count_ipower_actual++; } protected: @@ -543,7 +543,7 @@ TEST_F(DeviceTest, Labels) device will take longest to charge (and optionally how long it will take). */ TEST_F(DeviceTest, ChoosePrimary) { - GSList * device_list; + GList * device_list; IndicatorPowerDevice * a; IndicatorPowerDevice * b; @@ -581,8 +581,8 @@ TEST_F(DeviceTest, ChoosePrimary) }; device_list = NULL; - device_list = g_slist_append (device_list, a); - device_list = g_slist_append (device_list, b); + device_list = g_list_append (device_list, a); + device_list = g_list_append (device_list, b); for (int i=0, n=G_N_ELEMENTS(tests); i - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 . -*/ - -#include - -#include "dbus-listener.h" -#include "device.h" -#include "indicator-power.h" - -/*** -**** -***/ - -namespace -{ - void quiet_log_func (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) - { - // instantiating an indicator w/o a window causes lots - // of glib/gtk warnings... silence them so that they don't - // obscure any other warnings generated by the tests. - } - - void ensure_glib_initialized () - { - static bool initialized = false; - - if (G_UNLIKELY(!initialized)) - { - initialized = true; - g_log_set_handler ("Gtk", (GLogLevelFlags)(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING), quiet_log_func, NULL); - g_log_set_handler ("GLib-GObject", (GLogLevelFlags)(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING), quiet_log_func, NULL); - } - } -} - -/*** -**** -***/ - -class IndicatorTest : public ::testing::Test -{ - protected: - - IndicatorPowerDevice * ac_device; - IndicatorPowerDevice * battery_device; - - virtual void SetUp() - { - ensure_glib_initialized (); - - g_setenv( "GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); - - ac_device = indicator_power_device_new ( - "/org/freedesktop/UPower/devices/line_power_AC", - UP_DEVICE_KIND_LINE_POWER, - 0.0, UP_DEVICE_STATE_UNKNOWN, 0); - - battery_device = indicator_power_device_new ( - "/org/freedesktop/UPower/devices/battery_BAT0", - UP_DEVICE_KIND_BATTERY, - 52.871712, UP_DEVICE_STATE_DISCHARGING, 8834); - } - - virtual void TearDown() - { - ASSERT_EQ (1, G_OBJECT(battery_device)->ref_count); - ASSERT_EQ (1, G_OBJECT(ac_device)->ref_count); - g_object_unref (battery_device); - g_object_unref (ac_device); - } - - const char* GetAccessibleDesc (IndicatorPower * power) const - { - GList * entries = indicator_object_get_entries (INDICATOR_OBJECT(power)); - g_assert (g_list_length(entries) == 1); - IndicatorObjectEntry * entry = static_cast(entries->data); - const char * ret = entry->accessible_desc; - g_list_free (entries); - return ret; - } -}; - -/*** -**** -***/ - -TEST_F(IndicatorTest, GObjectNew) -{ - GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_TYPE, NULL)); - ASSERT_TRUE (o != NULL); - ASSERT_TRUE (IS_INDICATOR_POWER(o)); - g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls - g_object_unref (o); -} - -TEST_F(IndicatorTest, SetDevices) -{ - GSList * devices; - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - - devices = NULL; - devices = g_slist_append (devices, ac_device); - devices = g_slist_append (devices, battery_device); - indicator_power_set_devices (power, devices); - g_slist_free (devices); - - g_object_unref (power); -} - -TEST_F(IndicatorTest, DischargingStrings) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - GSList * devices = g_slist_append (NULL, battery_device); - - // give the indicator a discharging battery with 30 minutes of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, - INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, - INDICATOR_POWER_DEVICE_TIME, guint64(60*30), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (30 minutes left (50%))"); - - // give the indicator a discharging battery with 1 hour of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, - INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, - INDICATOR_POWER_DEVICE_TIME, guint64(60*60), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour left (50%))"); - - // give the indicator a discharging battery with 2 hours of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, - INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours left (100%))"); - - // give the indicator a discharging battery with over 12 hours of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_TIME, guint64(60*60*12 + 1), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery"); - - // give the indicator a discharging battery with 29 seconds left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_TIME, guint64(29), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (Unknown time left (100%))"); - - // what happens if the time estimate isn't available - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_TIME, guint64(0), - INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (50%)"); - - // what happens if the time estimate AND percentage isn't available - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_TIME, guint64(0), - INDICATOR_POWER_DEVICE_PERCENTAGE, 0.0, - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (not present)"); - - // cleanup - g_slist_free (devices); - g_object_unref (power); -} - -TEST_F(IndicatorTest, ChargingStrings) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - GSList * devices = g_slist_prepend (NULL, battery_device); - - // give the indicator a discharging battery with 1 hour of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, - INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, - INDICATOR_POWER_DEVICE_TIME, guint64(60*60), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour to charge (50%))"); - - // give the indicator a discharging battery with 2 hours of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours to charge (50%))"); - - // cleanup - g_slist_free (devices); - g_object_unref (power); -} - -TEST_F(IndicatorTest, ChargedStrings) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - GSList * devices = g_slist_append (NULL, battery_device); - - // give the indicator a discharging battery with 1 hour of life left - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, - INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, - INDICATOR_POWER_DEVICE_TIME, guint64(0), - NULL); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (charged)"); - - // cleanup - g_slist_free (devices); - g_object_unref (power); -} - -TEST_F(IndicatorTest, AvoidChargingBatteriesWithZeroSecondsLeft) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - - g_object_set (battery_device, - INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, - INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, - INDICATOR_POWER_DEVICE_TIME, guint64(0), - NULL); - IndicatorPowerDevice * bad_battery_device = indicator_power_device_new ( - "/org/freedesktop/UPower/devices/battery_BAT0", - UP_DEVICE_KIND_BATTERY, - 53, UP_DEVICE_STATE_CHARGING, 0); - - GSList * devices = NULL; - devices = g_slist_append (devices, battery_device); - devices = g_slist_append (devices, bad_battery_device); - indicator_power_set_devices (power, devices); - ASSERT_STREQ (GetAccessibleDesc(power), "Battery (53%)"); - - // cleanup - g_slist_free (devices); - g_object_unref (power); - g_object_unref (bad_battery_device); -} - -TEST_F(IndicatorTest, OtherDevices) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - - g_object_ref (battery_device); - GSList * devices = g_slist_append (NULL, battery_device); - - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/mouse", UP_DEVICE_KIND_MOUSE, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/ups", UP_DEVICE_KIND_UPS, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/keyboard", UP_DEVICE_KIND_KEYBOARD, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/pda", UP_DEVICE_KIND_PDA, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/phone", UP_DEVICE_KIND_PHONE, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/monitor", UP_DEVICE_KIND_MONITOR, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/media_player", UP_DEVICE_KIND_MEDIA_PLAYER, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/tablet", UP_DEVICE_KIND_TABLET, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/computer", UP_DEVICE_KIND_COMPUTER, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - devices = g_slist_append (devices, indicator_power_device_new ( - "/org/freedesktop/UPower/devices/unknown", UP_DEVICE_KIND_UNKNOWN, - 0, UP_DEVICE_STATE_UNKNOWN, 0)); - - indicator_power_set_devices (power, devices); - - // FIXME: this tests to confirm the code doesn't crash, - // but further tests would be helpful - - // cleanup - g_slist_free_full (devices, g_object_unref); - g_object_unref (power); -} - -TEST_F(IndicatorTest, NoDevices) -{ - IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); - - indicator_power_set_devices (power, NULL); - - // FIXME: this tests to confirm the code doesn't crash, - // but further tests would be helpful - - // cleanup - g_object_unref (power); -} diff --git a/tests/test-service.cc b/tests/test-service.cc new file mode 100644 index 0000000..cae3021 --- /dev/null +++ b/tests/test-service.cc @@ -0,0 +1,324 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 . + */ + +#include + +#include "device.h" +#include "service.h" + +/*** +**** +***/ + +namespace +{ + void quiet_log_func (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) + { + // instantiating an indicator w/o a window causes lots + // of glib/gtk warnings... silence them so that they don't + // obscure any other warnings generated by the tests. + } + + void ensure_glib_initialized () + { + static bool initialized = false; + + if (G_UNLIKELY(!initialized)) + { + initialized = true; + g_log_set_handler ("Gtk", (GLogLevelFlags)(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING), quiet_log_func, NULL); + g_log_set_handler ("GLib-GObject", (GLogLevelFlags)(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING), quiet_log_func, NULL); + } + } +} + +/*** +**** +***/ + +class IndicatorTest : public ::testing::Test +{ + protected: + + IndicatorPowerDevice * ac_device; + IndicatorPowerDevice * battery_device; + + virtual void SetUp() + { + ensure_glib_initialized (); + + g_setenv( "GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); + + ac_device = indicator_power_device_new ( + "/org/freedesktop/UPower/devices/line_power_AC", + UP_DEVICE_KIND_LINE_POWER, + 0.0, UP_DEVICE_STATE_UNKNOWN, 0); + + battery_device = indicator_power_device_new ( + "/org/freedesktop/UPower/devices/battery_BAT0", + UP_DEVICE_KIND_BATTERY, + 52.871712, UP_DEVICE_STATE_DISCHARGING, 8834); + } + + virtual void TearDown() + { + ASSERT_EQ (1, G_OBJECT(battery_device)->ref_count); + ASSERT_EQ (1, G_OBJECT(ac_device)->ref_count); + g_object_unref (battery_device); + g_object_unref (ac_device); + } + + const char* GetAccessibleDesc (IndicatorPower * power) const + { + GList * entries = indicator_object_get_entries (INDICATOR_OBJECT(power)); + g_assert (g_list_length(entries) == 1); + IndicatorObjectEntry * entry = static_cast(entries->data); + const char * ret = entry->accessible_desc; + g_list_free (entries); + return ret; + } +}; + +/*** +**** +***/ + +TEST_F(IndicatorTest, GObjectNew) +{ + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_TYPE, NULL)); + ASSERT_TRUE (o != NULL); + ASSERT_TRUE (IS_INDICATOR_POWER(o)); + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls + g_object_unref (o); +} + +TEST_F(IndicatorTest, SetDevices) +{ + GSList * devices; + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + + devices = NULL; + devices = g_slist_append (devices, ac_device); + devices = g_slist_append (devices, battery_device); + indicator_power_set_devices (power, devices); + g_slist_free (devices); + + g_object_unref (power); +} + +TEST_F(IndicatorTest, DischargingStrings) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + GSList * devices = g_slist_append (NULL, battery_device); + + // give the indicator a discharging battery with 30 minutes of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, + INDICATOR_POWER_DEVICE_TIME, guint64(60*30), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (30 minutes left (50%))"); + + // give the indicator a discharging battery with 1 hour of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, + INDICATOR_POWER_DEVICE_TIME, guint64(60*60), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour left (50%))"); + + // give the indicator a discharging battery with 2 hours of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours left (100%))"); + + // give the indicator a discharging battery with over 12 hours of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*12 + 1), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery"); + + // give the indicator a discharging battery with 29 seconds left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_TIME, guint64(29), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (Unknown time left (100%))"); + + // what happens if the time estimate isn't available + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_TIME, guint64(0), + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (50%)"); + + // what happens if the time estimate AND percentage isn't available + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_TIME, guint64(0), + INDICATOR_POWER_DEVICE_PERCENTAGE, 0.0, + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (not present)"); + + // cleanup + g_slist_free (devices); + g_object_unref (power); +} + +TEST_F(IndicatorTest, ChargingStrings) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + GSList * devices = g_slist_prepend (NULL, battery_device); + + // give the indicator a discharging battery with 1 hour of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, + INDICATOR_POWER_DEVICE_TIME, guint64(60*60), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour to charge (50%))"); + + // give the indicator a discharging battery with 2 hours of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours to charge (50%))"); + + // cleanup + g_slist_free (devices); + g_object_unref (power); +} + +TEST_F(IndicatorTest, ChargedStrings) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + GSList * devices = g_slist_append (NULL, battery_device); + + // give the indicator a discharging battery with 1 hour of life left + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, + INDICATOR_POWER_DEVICE_TIME, guint64(0), + NULL); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (charged)"); + + // cleanup + g_slist_free (devices); + g_object_unref (power); +} + +TEST_F(IndicatorTest, AvoidChargingBatteriesWithZeroSecondsLeft) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + + g_object_set (battery_device, + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, + INDICATOR_POWER_DEVICE_TIME, guint64(0), + NULL); + IndicatorPowerDevice * bad_battery_device = indicator_power_device_new ( + "/org/freedesktop/UPower/devices/battery_BAT0", + UP_DEVICE_KIND_BATTERY, + 53, UP_DEVICE_STATE_CHARGING, 0); + + GSList * devices = NULL; + devices = g_slist_append (devices, battery_device); + devices = g_slist_append (devices, bad_battery_device); + indicator_power_set_devices (power, devices); + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (53%)"); + + // cleanup + g_slist_free (devices); + g_object_unref (power); + g_object_unref (bad_battery_device); +} + +TEST_F(IndicatorTest, OtherDevices) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + + g_object_ref (battery_device); + GSList * devices = g_slist_append (NULL, battery_device); + + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/mouse", UP_DEVICE_KIND_MOUSE, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/ups", UP_DEVICE_KIND_UPS, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/keyboard", UP_DEVICE_KIND_KEYBOARD, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/pda", UP_DEVICE_KIND_PDA, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/phone", UP_DEVICE_KIND_PHONE, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/monitor", UP_DEVICE_KIND_MONITOR, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/media_player", UP_DEVICE_KIND_MEDIA_PLAYER, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/tablet", UP_DEVICE_KIND_TABLET, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/computer", UP_DEVICE_KIND_COMPUTER, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + devices = g_slist_append (devices, indicator_power_device_new ( + "/org/freedesktop/UPower/devices/unknown", UP_DEVICE_KIND_UNKNOWN, + 0, UP_DEVICE_STATE_UNKNOWN, 0)); + + indicator_power_set_devices (power, devices); + + // FIXME: this tests to confirm the code doesn't crash, + // but further tests would be helpful + + // cleanup + g_slist_free_full (devices, g_object_unref); + g_object_unref (power); +} + +TEST_F(IndicatorTest, NoDevices) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + + indicator_power_set_devices (power, NULL); + + // FIXME: this tests to confirm the code doesn't crash, + // but further tests would be helpful + + // cleanup + g_object_unref (power); +} -- cgit v1.2.3 From 8e052aeeb9498bc693306771e0dfbbdfda8d70e7 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 18 Jun 2013 20:59:56 -0500 Subject: remove INDICATORDIR and INDICATORICONSDIR from configure.ac --- configure.ac | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/configure.ac b/configure.ac index 5e29f36..20462fa 100644 --- a/configure.ac +++ b/configure.ac @@ -89,18 +89,6 @@ AC_ARG_ENABLE([localinstall], [with_localinstall=$enableval], [with_localinstall=no]) -########################### -# Indicator Info -########################### - -AS_IF([test "x$with_localinstall" = "xyes"], - [INDICATORDIR="${libdir}/indicators3/2/" - INDICATORICONSDIR="${datadir}/indicator-applet/icons/"], - [INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator3-0.4` - INDICATORICONSDIR=`$PKG_CONFIG --variable=iconsdir indicator3-0.4`]) -AC_SUBST(INDICATORDIR) -AC_SUBST(INDICATORICONSDIR) - ############################## # Custom Junk ############################## -- cgit v1.2.3 From 34cffaedb1fc4ea9a8f597b559cfbbfb5ee47638 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 18 Jun 2013 21:15:59 -0500 Subject: remove the short-term TODO --- TODO | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 54b363f..0000000 --- a/TODO +++ /dev/null @@ -1,7 +0,0 @@ -Short Term - - look for leaks by leaving running in valgrind - - fix broken tests - - install .indicator file - -Longer Term - - better coverage -- cgit v1.2.3 From eeb37d127e5bd3d34735b56c678ad1fd931d8034 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 18 Jun 2013 21:28:30 -0500 Subject: install the .indicator file into share/unity/indicators/ --- data/Makefile.am | 12 ++++++++++++ data/com.canonical.indicator.power | 9 +++++++++ data/power.indicator | 9 --------- 3 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 data/com.canonical.indicator.power delete mode 100644 data/power.indicator diff --git a/data/Makefile.am b/data/Makefile.am index 375c7ca..3143881 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,6 +1,18 @@ +# +# the indicator bus file +# + +indicatorsdir = $(prefix)/share/unity/indicators +indicators_DATA = com.canonical.indicator.power + +# +# the gettings +# + gsettings_in_file = com.canonical.indicator.power.gschema.xml.in gsettings_SCHEMAS = $(gsettings_in_file:.xml.in=.xml) +CLEANFILES += $(gsettings_SCHEMAS) @INTLTOOL_XML_NOMERGE_RULE@ diff --git a/data/com.canonical.indicator.power b/data/com.canonical.indicator.power new file mode 100644 index 0000000..1ebc075 --- /dev/null +++ b/data/com.canonical.indicator.power @@ -0,0 +1,9 @@ +[Indicator Service] +Name=indicator-power +ObjectPath=/com/canonical/indicator/power + +[desktop] +ObjectPath=/com/canonical/indicator/power/desktop + +[greeter] +ObjectPath=/com/canonical/indicator/power/greeter diff --git a/data/power.indicator b/data/power.indicator deleted file mode 100644 index 1ebc075..0000000 --- a/data/power.indicator +++ /dev/null @@ -1,9 +0,0 @@ -[Indicator Service] -Name=indicator-power -ObjectPath=/com/canonical/indicator/power - -[desktop] -ObjectPath=/com/canonical/indicator/power/desktop - -[greeter] -ObjectPath=/com/canonical/indicator/power/greeter -- cgit v1.2.3 From 1b56362cd709b620188fda0d1fa80743f7f9d8d9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 00:00:33 -0500 Subject: bump NEWS for 'make dist' --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 255db6f..a120944 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +13.10.0 + - Use the new GMenu indicator scheme + 12.10.5 - Fix a device display bug introduced in 12.10.3 (LP: #1075192) -- cgit v1.2.3 From f566ca0df0de10f82601d7fad7fd438c8f6963e3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 00:29:55 -0500 Subject: add a dbus service file for indicator-power... --- configure.ac | 9 +++++++++ data/Makefile.am | 20 ++++++++++++++++++-- data/indicator-power.service.in | 3 +++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 data/indicator-power.service.in diff --git a/configure.ac b/configure.ac index 20462fa..84e9423 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,15 @@ AC_ARG_ENABLE([localinstall], [with_localinstall=$enableval], [with_localinstall=no]) +########################### +# DBus Service Info +########################### + +AS_IF([test "x$with_localinstall" = "xyes"], + [DBUSSERVICEDIR="${datadir}/dbus-1/services/"], + [DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`]) +AC_SUBST(DBUSSERVICEDIR) + ############################## # Custom Junk ############################## diff --git a/data/Makefile.am b/data/Makefile.am index 3143881..c2ce65d 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,10 +1,26 @@ +BUILT_SOURCES= +CLEANFILES= +EXTRA_DIST= # # the indicator bus file # indicatorsdir = $(prefix)/share/unity/indicators -indicators_DATA = com.canonical.indicator.power +dist_indicators_DATA = com.canonical.indicator.power + +# +# the dbus service file +# + +dbus_servicesdir = $(DBUSSERVICEDIR) +dbus_services_DATA = indicator-power.service +dbus_services_in = $(dbus_services_DATA:.service=.service.in) +$(dbus_services_DATA): $(dbus_services_in) + $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ +BUILT_SOURCES += $(dbus_services_DATA) +CLEANFILES += $(dbus_services_DATA) +EXTRA_DIST += $(dbus_services_in) # # the gettings @@ -22,7 +38,7 @@ dist_noinst_DATA = \ com.canonical.indicator.power.gschema.xml \ $(gsettings_in_file) -CLEANFILES = \ +CLEANFILES += \ $(gsettings_SCHEMAS) MAINTAINERCLEANFILES = \ diff --git a/data/indicator-power.service.in b/data/indicator-power.service.in new file mode 100644 index 0000000..c59c69e --- /dev/null +++ b/data/indicator-power.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=com.canonical.indicator.power +Exec=@libexecdir@/indicator-power-service -- cgit v1.2.3 From 9cb5ad014fb1518f765de05ddaab677d082afbf1 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 00:45:50 -0500 Subject: put the service on the production busname --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 49fc4d7..f314906 100644 --- a/src/service.c +++ b/src/service.c @@ -27,7 +27,7 @@ #include "device-provider.h" #include "service.h" -#define BUS_NAME "power.indicator" +#define BUS_NAME "com.canonical.indicator.power" #define BUS_PATH "/com/canonical/indicator/power" #define SETTINGS_SHOW_TIME_S "show-time" -- cgit v1.2.3 From 34161b390539cd5638ad3a71720168b5510be4a8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 01:29:37 -0500 Subject: fix build issue in indicator_power_device_provider_get_devices(), reported by CI... --- src/device-provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device-provider.c b/src/device-provider.c index 361ab3c..05c6cd0 100644 --- a/src/device-provider.c +++ b/src/device-provider.c @@ -62,7 +62,7 @@ indicator_power_device_provider_default_init (IndicatorPowerDeviceProviderInterf GList * indicator_power_device_provider_get_devices (IndicatorPowerDeviceProvider * self) { - g_return_if_fail (INDICATOR_IS_POWER_DEVICE_PROVIDER (self)); + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE_PROVIDER (self), NULL); return INDICATOR_POWER_DEVICE_PROVIDER_GET_INTERFACE (self)->get_devices (self); } -- cgit v1.2.3 From eeb91e4b337a67c1656751942905129033c5a885 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 07:29:43 -0500 Subject: in configure.ac, add AM_PROG_AR to silence an autotools warning caused by the temporary static libraries created in src/ --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 84e9423..aa1cc12 100644 --- a/configure.ac +++ b/configure.ac @@ -21,6 +21,7 @@ AM_SILENT_RULES([yes]) AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CXX +AM_PROG_AR # Initialize libtool LT_PREREQ([2.2.6]) -- cgit v1.2.3 From dec4af40c78f85b36b995f69da66f30d07270852 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 09:43:11 -0500 Subject: lower the interval on the upower timer to make our updates more responsive --- src/device-provider-upower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device-provider-upower.c b/src/device-provider-upower.c index 7cc8858..6dd5029 100644 --- a/src/device-provider-upower.c +++ b/src/device-provider-upower.c @@ -89,7 +89,7 @@ static void emit_devices_changed_soon (IndicatorPowerDeviceProviderUPower * self) { if (self->priv->timer == 0) - self->priv->timer = g_timeout_add_seconds (1, on_timer, self); + self->priv->timer = g_timeout_add (333, on_timer, self); } /*** -- cgit v1.2.3 From 0ec4365a419db7d7b19e4bd415645ada50a5e5fc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 09:52:36 -0500 Subject: in provider-upower.c, clear its private hashtable in dispose() and destroy it in finalize() --- src/device-provider-upower.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/device-provider-upower.c b/src/device-provider-upower.c index 6dd5029..0fc5d91 100644 --- a/src/device-provider-upower.c +++ b/src/device-provider-upower.c @@ -305,7 +305,21 @@ my_dispose (GObject * o) g_clear_object (&p->upower_proxy); } - g_clear_pointer (&p->devices, g_hash_table_destroy); + g_hash_table_remove_all (p->devices); + + G_OBJECT_CLASS (indicator_power_device_provider_upower_parent_class)->dispose (o); +} + +static void +my_finalize (GObject * o) +{ + IndicatorPowerDeviceProviderUPower * self; + priv_t * p; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(o); + p = self->priv; + + g_hash_table_destroy (p->devices); G_OBJECT_CLASS (indicator_power_device_provider_upower_parent_class)->dispose (o); } @@ -320,6 +334,7 @@ indicator_power_device_provider_upower_class_init (IndicatorPowerDeviceProviderU GObjectClass * object_class = G_OBJECT_CLASS (klass); object_class->dispose = my_dispose; + object_class->finalize = my_finalize; g_type_class_add_private (klass, sizeof (IndicatorPowerDeviceProviderUPowerPriv)); -- cgit v1.2.3 From e2431a9ab55122b74397b4536ea95f769bc64999 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 10:01:19 -0500 Subject: in indicator_power_device_provider_get_devices, confirm that the get_devices function pointer isn't NULL before we call it. --- src/device-provider.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/device-provider.c b/src/device-provider.c index 05c6cd0..5ccf588 100644 --- a/src/device-provider.c +++ b/src/device-provider.c @@ -62,9 +62,18 @@ indicator_power_device_provider_default_init (IndicatorPowerDeviceProviderInterf GList * indicator_power_device_provider_get_devices (IndicatorPowerDeviceProvider * self) { + GList * devices; + IndicatorPowerDeviceProviderInterface * iface; + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE_PROVIDER (self), NULL); + iface = INDICATOR_POWER_DEVICE_PROVIDER_GET_INTERFACE (self); + + if (iface->get_devices != NULL) + devices = iface->get_devices (self); + else + devices = NULL; - return INDICATOR_POWER_DEVICE_PROVIDER_GET_INTERFACE (self)->get_devices (self); + return devices; } /** -- cgit v1.2.3 From 8f744774af079ec4c497377ae6dc4d833db8a360 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 10:10:50 -0500 Subject: remove the '--replace' command line argument; process management will be handled by Upstart --- src/main.c | 37 ++----------------------------------- src/service.c | 55 ++++++++++--------------------------------------------- src/service.h | 3 +-- 3 files changed, 13 insertions(+), 82 deletions(-) diff --git a/src/main.c b/src/main.c index 7bb6b92..ef615dc 100644 --- a/src/main.c +++ b/src/main.c @@ -33,37 +33,6 @@ **** ***/ -static gboolean replace = FALSE; - -static void -parse_command_line (int * argc, char *** argv) -{ - GError * error; - GOptionContext * option_context; - - static GOptionEntry entries[] = - { - { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "Replace the currently-running service", NULL }, - { NULL } - }; - - error = NULL; - option_context = g_option_context_new ("- indicator-power service"); - g_option_context_add_main_entries (option_context, entries, GETTEXT_PACKAGE); - if (!g_option_context_parse (option_context, argc, argv, &error)) - { - g_print ("option parsing failed: %s\n", error->message); - g_error_free (error); - exit (EXIT_FAILURE); - } - - g_option_context_free (option_context); -} - -/*** -**** -***/ - static void on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) { @@ -72,7 +41,7 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) } int -main (int argc, char ** argv) +main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { GMainLoop * loop; IndicatorPowerService * service; @@ -83,11 +52,9 @@ main (int argc, char ** argv) bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); - parse_command_line (&argc, &argv); - /* run */ device_provider = indicator_power_device_provider_upower_new (); - service = indicator_power_service_new (replace, device_provider); + service = indicator_power_service_new (device_provider); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); diff --git a/src/service.c b/src/service.c index f314906..012ef13 100644 --- a/src/service.c +++ b/src/service.c @@ -48,7 +48,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, - PROP_REPLACE, PROP_DEVICE_PROVIDER, LAST_PROP }; @@ -109,8 +108,6 @@ struct _IndicatorPowerServicePrivate GSimpleAction * header_action; GSimpleAction * show_time_action; - gboolean replace; - IndicatorPowerDevice * primary_device; GList * devices; /* IndicatorPowerDevice */ @@ -801,29 +798,6 @@ on_devices_changed (IndicatorPowerService * self) **** GObject virtual functions ***/ -static void -my_constructed (GObject * o) -{ - GBusNameOwnerFlags owner_flags; - IndicatorPowerService * self = INDICATOR_POWER_SERVICE(o); - priv_t * p = self->priv; - - /* own the name here in constructed() instead of init() - so that we know the value of the 'replace' property */ - owner_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; - if (p->replace) - owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; - - p->own_id = g_bus_own_name (G_BUS_TYPE_SESSION, - BUS_NAME, - owner_flags, - on_bus_acquired, - NULL, - on_name_lost, - self, - NULL); -} - static void my_get_property (GObject * o, guint property_id, @@ -835,10 +809,6 @@ my_get_property (GObject * o, switch (property_id) { - case PROP_REPLACE: - g_value_set_boolean (value, p->replace); - break; - case PROP_DEVICE_PROVIDER: g_value_set_object (value, p->device_provider); break; @@ -858,10 +828,6 @@ my_set_property (GObject * o, switch (property_id) { - case PROP_REPLACE: - self->priv->replace = g_value_get_boolean (value); - break; - case PROP_DEVICE_PROVIDER: indicator_power_service_set_device_provider (self, g_value_get_object (value)); break; @@ -938,6 +904,15 @@ indicator_power_service_init (IndicatorPowerService * self) G_CALLBACK(rebuild_header_now), self); g_signal_connect (p->settings, "changed::" SETTINGS_SHOW_TIME_S, G_CALLBACK(on_show_time_setting_changed), self); + + p->own_id = g_bus_own_name (G_BUS_TYPE_SESSION, + BUS_NAME, + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, + on_bus_acquired, + NULL, + on_name_lost, + self, + NULL); } static void @@ -946,7 +921,6 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) GObjectClass * object_class = G_OBJECT_CLASS (klass); object_class->dispose = my_dispose; - object_class->constructed = my_constructed; object_class->get_property = my_get_property; object_class->set_property = my_set_property; @@ -963,13 +937,6 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) properties[PROP_0] = NULL; - properties[PROP_REPLACE] = g_param_spec_boolean ( - "replace", - "Replace Service", - "Replace existing service", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); - properties[PROP_DEVICE_PROVIDER] = g_param_spec_object ( "device-provider", "Device Provider", @@ -985,11 +952,9 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) ***/ IndicatorPowerService * -indicator_power_service_new (gboolean replace, - IndicatorPowerDeviceProvider * device_provider) +indicator_power_service_new (IndicatorPowerDeviceProvider * device_provider) { GObject * o = g_object_new (INDICATOR_TYPE_POWER_SERVICE, - "replace", replace, "device-provider", device_provider, NULL); diff --git a/src/service.h b/src/service.h index 77cc362..76ed10f 100644 --- a/src/service.h +++ b/src/service.h @@ -64,8 +64,7 @@ struct _IndicatorPowerServiceClass GType indicator_power_service_get_type (void); -IndicatorPowerService * indicator_power_service_new (gboolean replace, - IndicatorPowerDeviceProvider * provider); +IndicatorPowerService * indicator_power_service_new (IndicatorPowerDeviceProvider * provider); void indicator_power_service_set_device_provider (IndicatorPowerService * self, IndicatorPowerDeviceProvider * provider); -- cgit v1.2.3 From 258f3ad689ae4ba49e2813a5051b4968d568f999 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 14:47:23 -0500 Subject: adjust device-provider-upower's timer to reduce how many times we pull the device's properties over the bus. --- src/device-provider-upower.c | 134 +++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/src/device-provider-upower.c b/src/device-provider-upower.c index 0fc5d91..05faeab 100644 --- a/src/device-provider-upower.c +++ b/src/device-provider-upower.c @@ -37,7 +37,12 @@ struct _IndicatorPowerDeviceProviderUPowerPriv DbusUPower * upower_proxy; GHashTable * devices; /* dbus object path --> IndicatorPowerDevice */ GCancellable * cancellable; - guint timer; + + /* a hashset of paths whose devices need to be refreshed */ + GHashTable * queued_paths; + + /* when this timer fires, the queued_paths will be refreshed */ + guint queued_paths_timer; }; typedef IndicatorPowerDeviceProviderUPowerPriv priv_t; @@ -57,45 +62,15 @@ G_DEFINE_TYPE_WITH_CODE ( indicator_power_device_provider_interface_init)); /*** -**** TIMER +**** UPOWER DBUS ***/ -/* - * Rebuilds are needed whenever upower devices are added, changed, or removed. - * - * Events often come in batches. For example, unplugging a power cable - * triggers a device-removed signal, and also a device-changed as the - * battery's state changes to 'discharging'. - * - * We use a small timer here to fold multiple upower events into a single - * IndicatorPowerDeviceProvider devices-changed signal. - */ - -static gboolean -on_timer (gpointer gself) -{ - IndicatorPowerDeviceProvider * provider; - IndicatorPowerDeviceProviderUPower * provider_upower; - - provider = INDICATOR_POWER_DEVICE_PROVIDER (gself); - indicator_power_device_provider_emit_devices_changed (provider); - - provider_upower = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); - provider_upower->priv->timer = 0; - return G_SOURCE_REMOVE; -} - static void -emit_devices_changed_soon (IndicatorPowerDeviceProviderUPower * self) +emit_devices_changed (IndicatorPowerDeviceProviderUPower * self) { - if (self->priv->timer == 0) - self->priv->timer = g_timeout_add (333, on_timer, self); + indicator_power_device_provider_emit_devices_changed (INDICATOR_POWER_DEVICE_PROVIDER (self)); } -/*** -**** UPOWER DBUS -***/ - static void on_upower_device_proxy_ready (GObject * o, GAsyncResult * res, gpointer gself) { @@ -138,7 +113,7 @@ on_upower_device_proxy_ready (GObject * o, GAsyncResult * res, gpointer gself) g_strdup (path), g_object_ref (device)); - emit_devices_changed_soon (self); + emit_devices_changed (self); g_object_unref (device); g_object_unref (tmp); @@ -158,6 +133,61 @@ update_device_from_object_path (IndicatorPowerDeviceProviderUPower * self, self); } +/* + * UPower doesn't seem to be sending PropertyChanged signals. + * + * Instead, it's got a DIY mechanism for notification: a DeviceChanged signal + * that doesn't tell us which property changed, so to refresh we need to + * rebuild all the properties with a GetAll() call. + * + * To make things worse, these DeviceChanged signals come fast and furious + * in common situations like disconnecting a power cable. + * + * This code tries to reduce bus traffic by adding a timer to wait a small bit + * before rebuilding our proxy's properties. This helps to fold multiple + * DeviceChanged events into a single rebuild. + */ + +/* rebuild all the proxies listed in our queued_paths hashset */ +static gboolean +on_queued_paths_timer (gpointer gself) +{ + gpointer path; + GHashTableIter iter; + IndicatorPowerDeviceProviderUPower * self; + priv_t * p; + + self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); + p = self->priv; + + /* create new proxies for all the queued paths */ + g_hash_table_iter_init (&iter, p->queued_paths); + while (g_hash_table_iter_next (&iter, &path, NULL)) + update_device_from_object_path (self, path); + + /* cleanup */ + g_hash_table_remove_all (p->queued_paths); + p->queued_paths_timer = 0; + return G_SOURCE_REMOVE; +} + +/* add the path to our queued_paths hashset and ensure the timer's running */ +static void +refresh_device_soon (IndicatorPowerDeviceProviderUPower * self, + const char * object_path) +{ + priv_t * p = self->priv; + + g_hash_table_add (p->queued_paths, g_strdup (object_path)); + + if (p->queued_paths_timer == 0) + p->queued_paths_timer = g_timeout_add (500, on_queued_paths_timer, self); +} + +/*** +**** +***/ + static void on_upower_device_enumerations_ready (GObject * proxy, GAsyncResult * res, @@ -182,26 +212,26 @@ on_upower_device_enumerations_ready (GObject * proxy, guint i; for (i=0; object_paths && object_paths[i]; i++) - update_device_from_object_path (gself, object_paths[i]); + refresh_device_soon (gself, object_paths[i]); g_strfreev (object_paths); } } static void -on_upower_device_added (DbusUPower * unused G_GNUC_UNUSED, - const char * object_path, - gpointer gself) +on_upower_device_changed (DbusUPower * unused G_GNUC_UNUSED, + const char * object_path, + gpointer gself) { - update_device_from_object_path (gself, object_path); + refresh_device_soon (gself, object_path); } static void -on_upower_device_changed (DbusUPower * unused G_GNUC_UNUSED, - const char * object_path, - gpointer gself) +on_upower_device_added (DbusUPower * unused G_GNUC_UNUSED, + const char * object_path, + gpointer gself) { - update_device_from_object_path (gself, object_path); + refresh_device_soon (gself, object_path); } static void @@ -213,7 +243,9 @@ on_upower_device_removed (DbusUPower * unused G_GNUC_UNUSED, self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER (gself); g_hash_table_remove (self->priv->devices, object_path); - emit_devices_changed_soon (self); + g_hash_table_remove (self->priv->queued_paths, object_path); + + emit_devices_changed (self); } static void @@ -291,11 +323,11 @@ my_dispose (GObject * o) g_clear_object (&p->cancellable); } - if (p->timer != 0) + if (p->queued_paths_timer != 0) { - g_source_remove (p->timer); + g_source_remove (p->queued_paths_timer); - p->timer = 0; + p->queued_paths_timer = 0; } if (p->upower_proxy != NULL) @@ -320,6 +352,7 @@ my_finalize (GObject * o) p = self->priv; g_hash_table_destroy (p->devices); + g_hash_table_destroy (p->queued_paths); G_OBJECT_CLASS (indicator_power_device_provider_upower_parent_class)->dispose (o); } @@ -364,6 +397,11 @@ indicator_power_device_provider_upower_init (IndicatorPowerDeviceProviderUPower g_free, g_object_unref); + p->queued_paths = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + dbus_upower_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, BUS_NAME, -- cgit v1.2.3