summaryrefslogtreecommitdiff
path: root/sensors-applet/active-sensor.c
diff options
context:
space:
mode:
Diffstat (limited to 'sensors-applet/active-sensor.c')
-rw-r--r--sensors-applet/active-sensor.c835
1 files changed, 835 insertions, 0 deletions
diff --git a/sensors-applet/active-sensor.c b/sensors-applet/active-sensor.c
new file mode 100644
index 0000000..84b84cc
--- /dev/null
+++ b/sensors-applet/active-sensor.c
@@ -0,0 +1,835 @@
+/*
+ * Copyright (C) 2005-2009 Alex Murray <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+
+#include <gconf/gconf-client.h>
+#include <gnome.h>
+
+#include "active-sensor.h"
+#include "sensors-applet-plugins.h"
+#include "sensors-applet-gconf.h"
+
+typedef enum {
+ VERY_LOW_SENSOR_VALUE = 0,
+ LOW_SENSOR_VALUE,
+ NORMAL_SENSOR_VALUE,
+ HIGH_SENSOR_VALUE,
+ VERY_HIGH_SENSOR_VALUE
+} SensorValueRange;
+
+/* Cast a given value to a valid SensorValueRange */
+#define SENSOR_VALUE_RANGE(x) ((SensorValueRange)(CLAMP(x, VERY_LOW_SENSOR_VALUE, VERY_HIGH_SENSOR_VALUE)))
+
+#define CAIRO_GRAPH_COLOR_GRADIENT 0.4
+
+static const gchar * const temp_overlay_icons[] = {
+ PIXMAPS_DIR "very-low-temp-icon.png",
+ PIXMAPS_DIR "low-temp-icon.png",
+ PIXMAPS_DIR "normal-temp-icon.png",
+ PIXMAPS_DIR "high-temp-icon.png",
+ PIXMAPS_DIR "very-high-temp-icon.png"
+};
+
+static gdouble sensor_value_range_normalised(gdouble value,
+ gdouble low_value,
+ gdouble high_value) {
+ return ((value - low_value)/(high_value - low_value));
+}
+
+static SensorValueRange sensor_value_range(gdouble sensor_value,
+ gdouble low_value,
+ gdouble high_value) {
+ gdouble range;
+ range = sensor_value_range_normalised(sensor_value, low_value, high_value)*(gdouble)(VERY_HIGH_SENSOR_VALUE);
+
+ /* check if need to round up, otherwise let int conversion
+ * round down for us and make sure it is a valid range
+ * value */
+ return SENSOR_VALUE_RANGE(((gint)range + ((range - ((gint)range)) >= 0.5)));
+}
+
+
+static gboolean active_sensor_execute_alarm(ActiveSensor *active_sensor,
+ NotifType notif_type) {
+ int pid;
+
+ sensors_applet_notify_active_sensor(active_sensor, notif_type);
+ g_debug("EXECUTING %s ALARM: %s",
+ (notif_type == LOW_ALARM ?
+ "LOW" : "HIGH"),
+ active_sensor->alarm_command[notif_type]);
+ pid = gnome_execute_shell(NULL,
+ active_sensor->alarm_command[notif_type]);
+ g_debug("Command executed in shell with pid %d", pid);
+
+ return (pid != -1);
+}
+
+static gboolean active_sensor_execute_low_alarm(ActiveSensor *active_sensor) {
+ return active_sensor_execute_alarm(active_sensor, LOW_ALARM);
+}
+
+static gboolean active_sensor_execute_high_alarm(ActiveSensor *active_sensor) {
+ return active_sensor_execute_alarm(active_sensor, HIGH_ALARM);
+}
+
+/* needs to be able to be called by the config dialog when the alarm
+ * command changes */
+void active_sensor_alarm_off(ActiveSensor *active_sensor,
+ NotifType notif_type) {
+ g_assert(active_sensor);
+
+ if (active_sensor->alarm_timeout_id[notif_type] != -1) {
+ g_debug("Disabling %s alarm.",
+ (notif_type == LOW_ALARM ? "LOW" : "HIGH"));
+ if (!g_source_remove(active_sensor->alarm_timeout_id[notif_type])) {
+ g_debug("Error removing alarm source");
+ }
+ g_free(active_sensor->alarm_command[notif_type]);
+ active_sensor->alarm_timeout_id[notif_type] = -1;
+
+ }
+ sensors_applet_notify_end(active_sensor, notif_type);
+}
+
+static void active_sensor_all_alarms_off(ActiveSensor *active_sensor) {
+ /* turn off any alarms */
+ int i;
+ for (i = 0; i < NUM_ALARMS; i++) {
+ if (active_sensor->alarm_timeout_id[i] >= 0) {
+ g_debug("-- turning off notif with type %d ---", i);
+ active_sensor_alarm_off(active_sensor, i);
+ }
+ }
+}
+
+static void active_sensor_alarm_on(ActiveSensor *active_sensor,
+ NotifType notif_type) {
+ GtkTreeModel *model;
+ GtkTreePath *tree_path;
+ GtkTreeIter iter;
+
+ g_assert(active_sensor);
+
+ model = gtk_tree_row_reference_get_model(active_sensor->sensor_row);
+ tree_path = gtk_tree_row_reference_get_path(active_sensor->sensor_row);
+
+ if (gtk_tree_model_get_iter(model, &iter, tree_path)) {
+
+ if (active_sensor->alarm_timeout_id[notif_type] == -1) {
+ /* alarm is not currently on */
+ gtk_tree_model_get(model,
+ &iter,
+ (notif_type == LOW_ALARM ?
+ LOW_ALARM_COMMAND_COLUMN :
+ HIGH_ALARM_COMMAND_COLUMN),
+ &(active_sensor->alarm_command[notif_type]),
+ ALARM_TIMEOUT_COLUMN, &(active_sensor->alarm_timeout),
+ -1);
+ g_debug("Activating alarm to repeat every %d seconds", active_sensor->alarm_timeout);
+
+ /* execute alarm once, then add to time to
+ keep repeating it */
+ active_sensor_execute_alarm(active_sensor, notif_type);
+ int timeout = (active_sensor->alarm_timeout <= 0 ?
+ G_MAXINT :
+ active_sensor->alarm_timeout);
+ switch (notif_type) {
+ case LOW_ALARM:
+ active_sensor->alarm_timeout_id[notif_type] = g_timeout_add_seconds(timeout,
+ (GSourceFunc)active_sensor_execute_low_alarm,
+ active_sensor);
+ break;
+ case HIGH_ALARM:
+ active_sensor->alarm_timeout_id[notif_type] = g_timeout_add_seconds(timeout,
+ (GSourceFunc)active_sensor_execute_high_alarm,
+ active_sensor);
+ break;
+ default:
+ g_debug("Unkown notif type: %d", notif_type);
+ }
+
+
+ }
+ }
+ gtk_tree_path_free(tree_path);
+
+}
+
+/**
+ * Compares two ActiveSensors and returns -1 if a comes before b in the tree,
+ * 0 if refer to same row, 1 if b comes before a
+ */
+gint active_sensor_compare(ActiveSensor *a, ActiveSensor *b) {
+ GtkTreePath *a_tree_path, *b_tree_path;
+ gint ret_val;
+
+ g_assert(a);
+ g_assert(b);
+
+ a_tree_path = gtk_tree_row_reference_get_path(a->sensor_row);
+ b_tree_path = gtk_tree_row_reference_get_path(b->sensor_row);
+
+ ret_val = gtk_tree_path_compare(a_tree_path, b_tree_path);
+
+ gtk_tree_path_free(a_tree_path);
+ gtk_tree_path_free(b_tree_path);
+
+ return ret_val;
+}
+
+static void active_sensor_update_icon(ActiveSensor *active_sensor,
+ GdkPixbuf *base_icon,
+ SensorType sensor_type) {
+
+ GdkPixbuf *overlay_icon, *new_icon;
+ const gchar *overlay_icon_filename = NULL;
+ SensorValueRange value_range;
+
+ g_assert(active_sensor);
+
+ /* select overlay icon
+ * depending on sensor
+ * value */
+ value_range = sensor_value_range(active_sensor->sensor_values[0],
+ active_sensor->sensor_low_value,
+ active_sensor->sensor_high_value);
+
+ if (sensor_type == TEMP_SENSOR) {
+ overlay_icon_filename = temp_overlay_icons[value_range];
+ }
+
+ /* load base icon */
+ new_icon = gdk_pixbuf_copy(base_icon);
+
+ /* only load overlay if required */
+ if (overlay_icon_filename) {
+ overlay_icon = gdk_pixbuf_new_from_file_at_size(overlay_icon_filename,
+ DEFAULT_ICON_SIZE,
+ DEFAULT_ICON_SIZE,
+ NULL);
+ if (overlay_icon) {
+ gdk_pixbuf_composite(overlay_icon, new_icon,
+ 0, 0,
+ DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE,
+ 0, 0,
+ 1.0, 1.0,
+ GDK_INTERP_BILINEAR,
+ 255);
+
+ g_object_unref(overlay_icon);
+ }
+ }
+ gtk_image_set_from_pixbuf(GTK_IMAGE(active_sensor->icon),
+ new_icon);
+ g_object_unref(new_icon);
+
+}
+
+static void active_sensor_update_graph(ActiveSensor *as) {
+ gdouble line_height;
+ gdouble width, height;
+ gdouble x, y;
+ cairo_t *cr;
+ cairo_pattern_t *pattern;
+ gint i;
+ GdkPixmap *pixmap;
+
+ width = as->graph->allocation.width;
+ height = as->graph->allocation.height;
+
+ /* only do if drawable - will not be drawable if not currently
+ * displayed on screen */
+ if (GDK_IS_DRAWABLE(as->graph->window)) {
+ /* use pixmap, draw to it, then use gdk to draw the
+ * pixmap onto the drawable surface of the graph to
+ * stop flickering */
+ pixmap = gdk_pixmap_new(as->graph->window,
+ width, height, -1);
+
+ cr = gdk_cairo_create(pixmap);
+
+ /* so we can set a clipping area, as well as fill the
+ * back of the graph black */
+ cairo_rectangle(cr,
+ 0, 0,
+ width,
+ height);
+ /* clip to rectangle and keep it as a path so can be
+ * filled below */
+ cairo_clip_preserve(cr);
+
+ /* use black for bg color of graphs */
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_fill(cr);
+
+
+ /* determine height to scale line at for each value -
+ * only do as many as will fit or the number of
+ * samples that we have */
+ for (i = 0; i < MIN(as->num_samples, width); i++) {
+ /* need to remove one more to make it line up
+ * properly when drawing */
+ x = width - i - 1;
+ y = height;
+
+ line_height = sensor_value_range_normalised(as->sensor_values[i],
+ as->sensor_low_value,
+ as->sensor_high_value) * height;
+
+
+
+ if (line_height > 0) {
+ cairo_move_to(cr,
+ x,
+ y);
+ cairo_line_to(cr, x,
+ y - line_height);
+ }
+
+ }
+ /* make lines a gradient from slightly darker than
+ * chosen color at bottom of graph, to slightly
+ * lighter than chosen color at top of graph */
+ pattern = cairo_pattern_create_linear(x, y,
+ x, 0);
+ cairo_pattern_add_color_stop_rgb(pattern,
+ 0,
+ as->graph_color.red / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT,
+ as->graph_color.green / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT,
+ as->graph_color.blue / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT);
+
+ cairo_pattern_add_color_stop_rgb(pattern,
+ height,
+ as->graph_color.red / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT,
+ as->graph_color.green / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT,
+ as->graph_color.blue / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT);
+
+ cairo_set_source(cr, pattern);
+ cairo_stroke(cr);
+ cairo_pattern_destroy(pattern);
+ cairo_destroy(cr);
+
+ /* now draw pixmap onto drawable surface */
+ gdk_draw_drawable(as->graph->window,
+ as->graph->style->fg_gc[GTK_WIDGET_STATE(as->graph)],
+ pixmap,
+ 0, 0,
+ 0, 0,
+ -1, -1);
+ /* don't need pixmap anymore */
+ g_object_unref(pixmap);
+ }
+}
+
+void active_sensor_destroy(ActiveSensor *active_sensor) {
+ g_debug("-- destroying active sensor label...");
+ gtk_object_destroy(GTK_OBJECT(active_sensor->label));
+
+ g_debug("-- destroying active sensor icon..");
+ gtk_object_destroy(GTK_OBJECT(active_sensor->icon));
+
+ g_debug("-- destroying active sensor value...");
+ gtk_object_destroy(GTK_OBJECT(active_sensor->value));
+
+ g_debug("-- destroying active sensor graph and frame...");
+ gtk_object_destroy(GTK_OBJECT(active_sensor->graph));
+ gtk_object_destroy(GTK_OBJECT(active_sensor->graph_frame));
+
+ g_debug("-- destroying active sensor values...");
+ g_free(active_sensor->sensor_values);
+
+ active_sensor_all_alarms_off(active_sensor);
+
+ g_free(active_sensor);
+}
+
+
+gboolean graph_expose_event_cb(GtkWidget *graph,
+ GdkEventExpose *event,
+ gpointer data) {
+ ActiveSensor *as;
+
+ as = (ActiveSensor *)data;
+
+ active_sensor_update_graph(as);
+ /* propagate event onwards */
+ return FALSE;
+}
+
+static void active_sensor_set_graph_dimensions(ActiveSensor *as,
+ gint width,
+ gint height) {
+ gdouble *old_values;
+ gint num_samples, old_num_samples;
+ gint graph_width, graph_height;
+
+ /* dimensions are really for graph frame, so need to remove
+ * extra width added by graph frame - make sure not less than
+ * 1 - always need atleast 1 sample */
+ graph_width = CLAMP(width - GRAPH_FRAME_EXTRA_WIDTH, 1, width - GRAPH_FRAME_EXTRA_WIDTH);
+ graph_height = CLAMP(height - GRAPH_FRAME_EXTRA_WIDTH, 1 , height - GRAPH_FRAME_EXTRA_WIDTH);
+
+ g_debug("setting graph dimensions to %d x %d", graph_width, graph_height);
+ num_samples = graph_width;
+
+ if (as->sensor_values) {
+ old_values = as->sensor_values;
+ old_num_samples = as->num_samples;
+
+ as->num_samples = num_samples;
+ as->sensor_values = g_malloc0(sizeof(gdouble)*as->num_samples);
+ memcpy(as->sensor_values,
+ old_values,
+ MIN(old_num_samples, as->num_samples)*sizeof(gdouble));
+
+ g_free(old_values);
+ } else {
+ as->sensor_values = g_malloc0(sizeof(gdouble)*num_samples);
+ as->num_samples = num_samples;
+ }
+
+ /* update graph frame size request */
+ gtk_widget_set_size_request(as->graph,
+ graph_width,
+ graph_height);
+}
+
+void active_sensor_update_graph_dimensions(ActiveSensor *as,
+ gint sizes[2]) {
+ active_sensor_set_graph_dimensions(as, sizes[0], sizes[1]);
+ active_sensor_update_graph(as);
+}
+
+ActiveSensor *active_sensor_new(SensorsApplet *sensors_applet,
+ GtkTreeRowReference *sensor_row) {
+ ActiveSensor *active_sensor;
+ PanelAppletOrient orient;
+ gint graph_size;
+ gboolean horizontal;
+
+ g_assert(sensors_applet);
+ g_assert(sensor_row);
+
+ g_debug("creating new active sensor");
+
+ active_sensor = g_new0(ActiveSensor, 1);
+ active_sensor->sensors_applet = sensors_applet;
+
+ active_sensor->sensor_row = sensor_row;
+
+ int i;
+ for (i = 0; i < NUM_NOTIFS; i++) {
+ active_sensor->alarm_timeout_id[i] = -1;
+ }
+
+ active_sensor->label = gtk_label_new("");
+ active_sensor->value = gtk_label_new("");
+ active_sensor->icon = gtk_image_new();
+
+ active_sensor->graph = gtk_drawing_area_new();
+ active_sensor->graph_frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(active_sensor->graph_frame),
+ GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(active_sensor->graph_frame),
+ active_sensor->graph);
+ gtk_widget_add_events(active_sensor->graph_frame,
+ GDK_ALL_EVENTS_MASK);
+
+ /* need to set size according to orientation */
+ orient = panel_applet_get_orient(active_sensor->sensors_applet->applet);
+ graph_size = panel_applet_gconf_get_int(active_sensor->sensors_applet->applet,
+ GRAPH_SIZE, NULL);
+
+ horizontal = ((orient == PANEL_APPLET_ORIENT_UP) ||
+ (orient == PANEL_APPLET_ORIENT_DOWN));
+
+ active_sensor_set_graph_dimensions(active_sensor,
+ (horizontal ? graph_size : sensors_applet->size),
+ (horizontal ? sensors_applet->size : graph_size));
+
+ g_signal_connect(G_OBJECT(active_sensor->graph),
+ "expose_event",
+ G_CALLBACK(graph_expose_event_cb),
+ active_sensor);
+
+ active_sensor->updated = FALSE;
+ return active_sensor;
+}
+
+static void active_sensor_update_sensor_value(ActiveSensor *as,
+ gdouble sensor_value) {
+
+ /* only if have more than 1 sample stored */
+ if (as->num_samples > 1) {
+ memmove(&(as->sensor_values[1]),
+ as->sensor_values,
+ (as->num_samples - 1)*sizeof(gdouble));
+ }
+
+ as->sensor_values[0] = sensor_value;
+}
+
+void active_sensor_update(ActiveSensor *active_sensor,
+ SensorsApplet *sensors_applet) {
+
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ /* instance data from the tree for this sensor */
+ gchar *sensor_path = NULL;
+ gchar *sensor_id = NULL;
+ gchar *sensor_label = NULL;
+ SensorType sensor_type;
+ gchar *sensor_interface;
+ gboolean sensor_enabled;
+ gdouble sensor_low_value;
+ gdouble sensor_high_value;
+ gboolean sensor_alarm_enabled;
+ gdouble sensor_multiplier;
+ gdouble sensor_offset;
+ gdouble sensor_value;
+ GdkPixbuf *icon_pixbuf;
+ gchar *graph_color;
+
+ /* to build the list of labels as we go */
+ gchar *value_text = NULL;
+ gchar *old_value_text;
+
+ TemperatureScale scale;
+ DisplayMode display_mode;
+
+ GError *error = NULL;
+
+ gchar *tooltip = NULL;
+ gchar *value_tooltip = NULL;
+
+ /* hidden gconf options */
+ GConfClient *client;
+ gint font_size = 0;
+ gboolean hide_units = FALSE;
+
+ g_assert(active_sensor);
+ g_assert(active_sensor->sensor_row);
+ g_assert(sensors_applet);
+
+ model = gtk_tree_row_reference_get_model(active_sensor->sensor_row);
+ path = gtk_tree_row_reference_get_path(active_sensor->sensor_row);
+
+ /* if can successfully get iter can proceed */
+ if (gtk_tree_model_get_iter(model, &iter, path)) {
+ gtk_tree_path_free(path);
+ gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors),
+ &iter,
+ PATH_COLUMN, &sensor_path,
+ ID_COLUMN, &sensor_id,
+ LABEL_COLUMN, &sensor_label,
+ INTERFACE_COLUMN, &sensor_interface,
+ SENSOR_TYPE_COLUMN, &sensor_type,
+ ENABLE_COLUMN, &sensor_enabled,
+ LOW_VALUE_COLUMN, &sensor_low_value,
+ HIGH_VALUE_COLUMN, &sensor_high_value,
+ ALARM_ENABLE_COLUMN, &sensor_alarm_enabled,
+ MULTIPLIER_COLUMN, &sensor_multiplier,
+ OFFSET_COLUMN, &sensor_offset,
+ ICON_PIXBUF_COLUMN, &icon_pixbuf,
+ GRAPH_COLOR_COLUMN, &graph_color,
+ -1);
+
+
+ SensorsAppletPluginGetSensorValue get_sensor_value;
+ /* only call function if is in hash table for plugin */
+ if ((get_sensor_value = sensors_applet_plugins_get_sensor_value_func(sensors_applet, sensor_interface)) != NULL) {
+ sensor_value = get_sensor_value(sensor_path,
+ sensor_id,
+ sensor_type,
+ &error);
+
+
+ if (error) {
+ g_debug("Error updating active sensor: %s", error->message);
+ sensors_applet_notify_active_sensor(active_sensor,
+ SENSOR_INTERFACE_ERROR);
+
+ /* hard code text as ERROR */
+ value_text = g_strdup(_("ERROR"));
+ value_tooltip = g_strdup_printf("- %s", error->message);
+ g_error_free(error);
+ error = NULL;
+
+ /* set sensor value to an error code -
+ * note this is not unique */
+ sensor_value = -1;
+ } else {
+ /* use hidden gconf key for hide_units */
+
+ if ((client = gconf_client_get_default()) != NULL) {
+ hide_units = gconf_client_get_bool(client,
+ "/apps/sensors-applet/" HIDE_UNITS,
+ &error);
+ if (error) {
+ g_debug("Could not get hide units from GConf - assuming false");
+ hide_units = FALSE;
+ g_error_free(error);
+ error = NULL;
+ }
+
+ g_object_unref(client);
+ }
+
+
+ /* scale value and set text using this
+ * value */
+ switch (sensor_type) {
+ case TEMP_SENSOR:
+
+ scale = (TemperatureScale)panel_applet_gconf_get_int(sensors_applet->applet, TEMPERATURE_SCALE, NULL);
+ /* scale value */
+ sensor_value = sensors_applet_convert_temperature(sensor_value,
+ CELSIUS,
+ scale);
+
+ sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
+ switch (scale) {
+ case FAHRENHEIT:
+ value_text = g_strdup_printf("%2.0f %s", sensor_value, (hide_units ? "" : UNITS_FAHRENHEIT));
+ /* tooltip should
+ * always display
+ * units */
+ value_tooltip = g_strdup_printf("%2.0f %s", sensor_value, UNITS_FAHRENHEIT);
+
+ break;
+ case CELSIUS:
+ value_text = g_strdup_printf("%2.0f %s", sensor_value, (hide_units ? "" : UNITS_CELSIUS));
+ value_tooltip = g_strdup_printf("%2.0f %s", sensor_value, UNITS_CELSIUS);
+ break;
+ case KELVIN:
+ value_text = g_strdup_printf("%2.0f", sensor_value);
+ value_tooltip = g_strdup(value_text);
+ break;
+ }
+ break;
+
+ case FAN_SENSOR:
+ sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
+ value_text = g_strdup_printf("%4.0f %s", sensor_value, (hide_units ? "" : UNITS_RPM));
+ value_tooltip = g_strdup_printf("%4.0f %s", sensor_value, UNITS_RPM);
+
+ break;
+
+ case VOLTAGE_SENSOR:
+ sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
+ value_text = g_strdup_printf("%4.2f %s", sensor_value, (hide_units ? "" : UNITS_VOLTAGE));
+ value_tooltip = g_strdup_printf("%4.2f %s", sensor_value, UNITS_VOLTAGE);
+
+ break;
+
+ case CURRENT_SENSOR:
+ sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
+ value_text = g_strdup_printf("%4.2f %s", sensor_value, (hide_units ? "" : UNITS_CURRENT));
+ value_tooltip = g_strdup_printf("%4.2f %s", sensor_value, UNITS_CURRENT);
+ break;
+
+ } /* end switch(sensor_type) */
+ } /* end else on error */
+
+ /* setup for tooltips */
+ tooltip = g_strdup_printf("%s %s", sensor_label, value_tooltip);
+ g_free(value_tooltip);
+
+ /* only do icons and labels / graphs if needed */
+ display_mode = panel_applet_gconf_get_int(sensors_applet->applet,
+ DISPLAY_MODE,
+ NULL);
+
+ /* most users wont have a font size set */
+ if ((client = gconf_client_get_default()) != NULL) {
+ font_size = gconf_client_get_int(client,
+ "/apps/sensors-applet/" FONT_SIZE,
+ &error);
+ if (error) {
+ g_debug("Could not get font size from GConf - assuming default size");
+ font_size = 0;
+ g_error_free(error);
+ error = NULL;
+ }
+
+ g_object_unref(client);
+ }
+
+
+ /* do icon if needed */
+ if (display_mode == DISPLAY_ICON ||
+ display_mode == DISPLAY_ICON_WITH_VALUE) {
+ /* update icon if icon range has changed if no
+ * update has been done before */
+ if ((sensor_value_range(sensor_value, sensor_low_value, sensor_high_value) != sensor_value_range(active_sensor->sensor_values[0], active_sensor->sensor_low_value, active_sensor->sensor_high_value)) || !(active_sensor->updated)) {
+ active_sensor_update_sensor_value(active_sensor,
+ sensor_value);
+ active_sensor->sensor_low_value = sensor_low_value;
+ active_sensor->sensor_high_value = sensor_high_value;
+ active_sensor_update_icon(active_sensor, icon_pixbuf, sensor_type);
+ }
+ /* always update tooltip */
+ gtk_widget_set_tooltip_text(active_sensor->icon,
+ tooltip);
+ }
+ active_sensor_update_sensor_value(active_sensor,
+ sensor_value);
+ active_sensor->sensor_low_value = sensor_low_value;
+ active_sensor->sensor_high_value = sensor_high_value;
+
+ /* do graph if needed */
+ if (display_mode == DISPLAY_GRAPH) {
+ /* update graph color in case has changed */
+ gdk_color_parse(graph_color,
+ &(active_sensor->graph_color));
+
+ active_sensor_update_graph(active_sensor);
+ gtk_widget_set_tooltip_text(active_sensor->graph,
+ tooltip);
+
+ }
+
+ old_value_text = value_text;
+
+ if (sensor_alarm_enabled) {
+ if (sensor_value >= sensor_high_value ||
+ sensor_value <= sensor_low_value) {
+ /* make value text red and
+ * activate alarm */
+ if (display_mode == DISPLAY_LABEL_WITH_VALUE ||
+ display_mode == DISPLAY_ICON_WITH_VALUE ||
+ display_mode == DISPLAY_VALUE) {
+ value_text = g_markup_printf_escaped("<span foreground=\"#FF0000\">%s</span>", old_value_text);
+
+ g_free(old_value_text);
+ }
+ /* could have both coditions at once */
+ if (sensor_value >= sensor_high_value) {
+ active_sensor_alarm_on(active_sensor, HIGH_ALARM);
+ }
+
+ if (sensor_value <= sensor_low_value) {
+ active_sensor_alarm_on(active_sensor, LOW_ALARM);
+ }
+
+ } else {
+ /* make sure alarms are off */
+ active_sensor_all_alarms_off(active_sensor);
+ }
+ } else { /* else for if alarm enabled */
+ /* make sure all alarms are off */
+ active_sensor_all_alarms_off(active_sensor);
+ }
+
+ /* do value label */
+ if (display_mode == DISPLAY_LABEL_WITH_VALUE ||
+ display_mode == DISPLAY_ICON_WITH_VALUE ||
+ display_mode == DISPLAY_VALUE) {
+ if (font_size) {
+ old_value_text = value_text;
+
+ value_text = g_strdup_printf("<span font_desc=\"%d\">%s</span>", font_size, old_value_text);
+ g_free(old_value_text);
+ }
+ gtk_label_set_markup(GTK_LABEL(active_sensor->value),
+ value_text);
+
+
+ gtk_widget_set_tooltip_text(active_sensor->value,
+ tooltip);
+ }
+ /* finished with value text */
+ g_free(value_text);
+
+ /* do label label */
+ if (display_mode == DISPLAY_LABEL_WITH_VALUE) {
+ if (font_size) {
+ old_value_text = sensor_label;
+ sensor_label = g_strdup_printf("<span font_desc=\"%d\">%s</span>", font_size, old_value_text);
+ g_free(old_value_text);
+ }
+ gtk_label_set_markup(GTK_LABEL(active_sensor->label),
+ sensor_label);
+ gtk_widget_set_tooltip_text(active_sensor->label,
+ tooltip);
+
+ }
+
+ g_free(tooltip);
+ } else {
+ g_debug("no get_sensor_value function yet installed for interface %s.", sensor_interface);
+ }
+ g_free(sensor_path);
+ g_free(sensor_id);
+ g_free(sensor_label);
+ g_free(sensor_interface);
+ g_free(graph_color);
+ g_object_unref(icon_pixbuf);
+
+ } else {
+ g_debug("Error getting iter when updating sensor...");
+
+ }
+ active_sensor->updated = TRUE;
+
+}
+
+/* to be called when the icon within the GtkRowReference that this
+ * sensor references is changed - updates icon based upon value in the
+ * ActiveSensor */
+void active_sensor_icon_changed(ActiveSensor *active_sensor,
+ SensorsApplet *sensors_applet) {
+
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ SensorType sensor_type;
+ GdkPixbuf *icon_pixbuf;
+
+ g_assert(active_sensor);
+ g_assert(sensors_applet);
+
+ model = gtk_tree_row_reference_get_model(active_sensor->sensor_row);
+ path = gtk_tree_row_reference_get_path(active_sensor->sensor_row);
+
+ /* if can successfully get iter can proceed */
+ if (gtk_tree_model_get_iter(model, &iter, path)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors),
+ &iter,
+ SENSOR_TYPE_COLUMN, &sensor_type,
+ ICON_PIXBUF_COLUMN, &icon_pixbuf,
+ -1);
+
+ active_sensor_update_icon(active_sensor,
+ icon_pixbuf,
+ sensor_type);
+ g_object_unref(icon_pixbuf);
+ }
+ gtk_tree_path_free(path);
+}