/*
* Copyright (C) 2005 Alex Murray <pragmatine@gmail.com>
*
* 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
*/
#include "active-sensor.h"
#include "sensors-applet-gconf.h"
/* returns a constant string containing the pango fontsize, defaults
to medium if error - this value is owned and cannot be freed by the
caller */
static const gchar *active_sensor_get_font_size(SensorsApplet *sensors_applet) {
FontSize font_size;
font_size = panel_applet_gconf_get_int(sensors_applet->applet, FONT_SIZE, NULL);
switch (font_size) {
case XX_LARGE:
return XX_LARGE_TEXT;
case X_LARGE:
return X_LARGE_TEXT;
case LARGE:
return LARGE_TEXT;
case MEDIUM:
return MEDIUM_TEXT;
case SMALL:
return SMALL_TEXT;
case X_SMALL:
return X_SMALL_TEXT;
case XX_SMALL:
return XX_SMALL_TEXT;
default:
return MEDIUM_TEXT;
}
}
static int active_sensor_get_sensor_value_ceiling(gdouble sensor_value, SensorType sensor_type) {
switch(sensor_type) {
case TEMP_SENSOR:
if (sensor_value < VERY_LOW_TEMP_UPPER_VALUE) {
return VERY_LOW_TEMP_UPPER_VALUE;
}
if (sensor_value < LOW_TEMP_UPPER_VALUE) {
return LOW_TEMP_UPPER_VALUE;
}
if (sensor_value < NORMAL_TEMP_UPPER_VALUE) {
return NORMAL_TEMP_UPPER_VALUE;
}
if (sensor_value < HIGH_TEMP_UPPER_VALUE) {
return HIGH_TEMP_UPPER_VALUE;
}
return VERY_HIGH_TEMP_UPPER_VALUE;
break;
case FAN_SENSOR:
if (sensor_value < VERY_LOW_TEMP_UPPER_VALUE) {
return VERY_LOW_FAN_UPPER_VALUE;
}
if (sensor_value < LOW_FAN_UPPER_VALUE) {
return LOW_FAN_UPPER_VALUE;
}
if (sensor_value < NORMAL_FAN_UPPER_VALUE) {
return NORMAL_FAN_UPPER_VALUE;
}
if (sensor_value < HIGH_FAN_UPPER_VALUE) {
return HIGH_FAN_UPPER_VALUE;
}
return VERY_HIGH_FAN_UPPER_VALUE;
break;
default:
return 0;
}
}
static IconSize active_sensor_get_icon_size(SensorsApplet *sensors_applet) {
FontSize font_size;
font_size = panel_applet_gconf_get_int(sensors_applet->applet, FONT_SIZE, NULL);
switch (font_size) {
case XX_LARGE:
return XX_LARGE_ICON_SIZE;
case X_LARGE:
return X_LARGE_ICON_SIZE;
case LARGE:
return LARGE_ICON_SIZE;
case MEDIUM:
return MEDIUM_ICON_SIZE;
case SMALL:
return SMALL_ICON_SIZE;
case X_SMALL:
return X_SMALL_ICON_SIZE;
case XX_SMALL:
return XX_SMALL_ICON_SIZE;
default:
return MEDIUM_ICON_SIZE;
}
}
static gboolean active_sensor_execute_alarm(const gchar *alarm_command) {
g_debug("EXECUTING ALARM: %s\n", alarm_command);
gnome_execute_shell(NULL, alarm_command);
return TRUE;
}
/* needs to be able to be called by the config dialog when the alarm
* command changes */
void active_sensor_alarm_off(ActiveSensor *active_sensor) {
g_assert(active_sensor != NULL);
if (active_sensor->alarm_timeout_id != -1) {
g_debug("Disabling alarm.\n");
/* alarm is on, cycle through list of alarm_commands
* and free this one */
if (!g_source_remove(active_sensor->alarm_timeout_id)) {
g_debug("Error removing alarm source\n");
}
g_free(active_sensor->alarm_command);
active_sensor->alarm_timeout_id = -1;
}
}
static void active_sensor_alarm_on(ActiveSensor *active_sensor) {
GtkTreeModel *model;
GtkTreePath *tree_path;
GtkTreeIter iter;
guint alarm_timeout;
g_assert(active_sensor != NULL);
model = gtk_tree_row_reference_get_model(active_sensor->sensor_row);
tree_path = gtk_tree_row_reference_get_path(active_sensor->sensor_row);
g_debug("Activating alarm...\n");
if (gtk_tree_model_get_iter(model, &iter, tree_path)) {
if (active_sensor->alarm_timeout_id == -1) {
/* alarm is not currently on */
gtk_tree_model_get(model,
&iter,
ALARM_COMMAND_COLUMN, &(active_sensor->alarm_command),
ALARM_TIMEOUT_COLUMN, &alarm_timeout,
-1);
/* execute alarm once, then add to time to
keep repeating it */
active_sensor_execute_alarm(active_sensor->alarm_command);
if (alarm_timeout <= 0) {
active_sensor->alarm_timeout_id = g_timeout_add(G_MAXINT,
(GSourceFunc)active_sensor_execute_alarm,
active_sensor->alarm_command);
} else {
active_sensor->alarm_timeout_id = g_timeout_add(alarm_timeout * 1000,
(GSourceFunc)active_sensor_execute_alarm,
active_sensor->alarm_command);
}
}
}
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 != NULL);
g_assert(b != NULL);
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, const gchar *base_icon, int icon_size, SensorType sensor_type) {
GdkPixbuf *scaled_icon, *overlay_icon;
const gchar *overlay_icon_filename = NULL;
g_assert(active_sensor != NULL);
/* select overlay icon
* depending on sensor
* value */
switch (active_sensor_get_sensor_value_ceiling(active_sensor->sensor_value, sensor_type)) {
case VERY_LOW_TEMP_UPPER_VALUE:
overlay_icon_filename = VERY_LOW_TEMP_ICON;
break;
case LOW_TEMP_UPPER_VALUE:
overlay_icon_filename = LOW_TEMP_ICON;
break;
case NORMAL_TEMP_UPPER_VALUE:
overlay_icon_filename = NORMAL_TEMP_ICON;
break;
case HIGH_TEMP_UPPER_VALUE:
overlay_icon_filename = HIGH_TEMP_ICON;
break;
case VERY_HIGH_TEMP_UPPER_VALUE:
overlay_icon_filename = VERY_HIGH_TEMP_ICON;
break;
case VERY_LOW_FAN_UPPER_VALUE:
overlay_icon_filename = VERY_LOW_FAN_ICON;
break;
case LOW_FAN_UPPER_VALUE:
overlay_icon_filename = LOW_FAN_ICON;
break;
case NORMAL_FAN_UPPER_VALUE:
overlay_icon_filename = NORMAL_FAN_ICON;
break;
case HIGH_FAN_UPPER_VALUE:
overlay_icon_filename = HIGH_FAN_ICON;
break;
case VERY_HIGH_FAN_UPPER_VALUE:
overlay_icon_filename = VERY_HIGH_FAN_ICON;
break;
default:
overlay_icon_filename = NULL;
}
/* load base icon */
scaled_icon = gdk_pixbuf_new_from_file_at_size(base_icon,
icon_size,
icon_size,
NULL);
/* only load overlay if required */
if (overlay_icon_filename) {
overlay_icon = gdk_pixbuf_new_from_file_at_size(overlay_icon_filename,
icon_size,
icon_size,
NULL);
if (overlay_icon) {
g_debug("Updating overlay icon: %s\n", overlay_icon_filename);
gdk_pixbuf_composite(overlay_icon, scaled_icon,
0, 0,
icon_size, icon_size,
0, 0,
1.0, 1.0,
GDK_INTERP_BILINEAR,
255);
g_object_unref(overlay_icon);
}
}
if (active_sensor->icon) {
gtk_image_set_from_pixbuf(active_sensor->icon,
scaled_icon);
} else {
active_sensor->icon = GTK_IMAGE(gtk_image_new_from_pixbuf(scaled_icon));
}
g_object_unref(scaled_icon);
}
void active_sensor_update(ActiveSensor *active_sensor, SensorsApplet *sensors_applet) {
g_assert(active_sensor != NULL);
g_assert(active_sensor->sensor_row != NULL);
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;
SensorInterface sensor_interface;
gboolean sensor_enabled;
gdouble sensor_alarm_value;
gboolean sensor_alarm_enabled;
AlarmType sensor_alarm_type;
gdouble sensor_multiplier;
gdouble sensor_offset;
gdouble old_sensor_value, sensor_value;
gchar *icon_filename;
/* used to see if size of icon has changed */
GdkPixbuf *pixbuf;
/* to build the list of labels as we go */
gchar *label_text = NULL;
gchar *value_text = NULL;
gchar *old_value_text;
const gchar *font_size;
GError *error = NULL;
int icon_size;
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,
ALARM_VALUE_COLUMN, &sensor_alarm_value,
ALARM_TYPE_COLUMN, &sensor_alarm_type,
ALARM_ENABLE_COLUMN, &sensor_alarm_enabled,
MULTIPLIER_COLUMN, &sensor_multiplier,
OFFSET_COLUMN, &sensor_offset,
ICON_FILENAME_COLUMN, &icon_filename,
-1);
/* get font size */
font_size = active_sensor_get_font_size(sensors_applet);
/* only call function if is not NULL */
if (sensors_applet->get_sensor_value[sensor_interface]) {
sensor_value = sensors_applet->get_sensor_value[sensor_interface](sensor_path,
sensor_id,
sensor_type,
&error);
if (error) {
g_debug("Error updating active sensor: %s\n", error->message);
value_text = g_strdup(error->message);
g_error_free(error);
error = NULL;
} else {
switch (sensor_type) {
case TEMP_SENSOR:
if (panel_applet_gconf_get_bool(sensors_applet->applet, FARENHEIT, NULL)) {
/* convert to
* Fahrenheit */
sensor_value = (9.0 * sensor_value / 5.0) + 32.0;
/* now scale
* in
* Fahrenheit */
sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
value_text = g_strdup_printf("%2.0f%s", sensor_value, (panel_applet_gconf_get_bool(sensors_applet->applet, SHOW_UNITS, NULL) ? "\302\260F" : ""));
/* now convert
* back to
* celcius so
* can use to
* set the
* icon
* overlay */
sensor_value = (sensor_value - 32.0) * 5.0 / 9.0;
} else {
sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
value_text = g_strdup_printf("%2.0f%s", sensor_value, (panel_applet_gconf_get_bool(sensors_applet->applet, SHOW_UNITS, NULL) ? "\302\260C" : ""));
}
break;
case FAN_SENSOR:
sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
value_text = g_strdup_printf("%4.0f%s", sensor_value, (panel_applet_gconf_get_bool(sensors_applet->applet, SHOW_UNITS, NULL) ? _("RPM") : ""));
break;
case VOLTAGE_SENSOR:
sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
value_text = g_strdup_printf("%4.2f%s", sensor_value, (panel_applet_gconf_get_bool(sensors_applet->applet, SHOW_UNITS, NULL) ? _("V") : ""));
break;
case CURRENT_SENSOR:
sensor_value = (sensor_value * sensor_multiplier) + sensor_offset;
value_text = g_strdup_printf("%4.2f%s", sensor_value, (panel_applet_gconf_get_bool(sensors_applet->applet, SHOW_UNITS, NULL) ? _("A") : ""));
break;
default:
g_assert_not_reached();
} /* end switch(sensor_type) */
icon_size = active_sensor_get_icon_size(sensors_applet);
/* update icon if icon range has changed, or
* icon size has changed, or if no icon
* already exists */
if ((active_sensor_get_sensor_value_ceiling(sensor_value, sensor_type) != active_sensor_get_sensor_value_ceiling(active_sensor->sensor_value, sensor_type)) || (active_sensor->icon == NULL)) {
active_sensor->sensor_value = sensor_value;
active_sensor_update_icon(active_sensor, icon_filename, icon_size, sensor_type);
} else if (active_sensor->icon != NULL) {
g_object_get(active_sensor->icon,
"pixbuf", &pixbuf,
NULL);
if (gdk_pixbuf_get_width(pixbuf) != icon_size) {
active_sensor->sensor_value = sensor_value;
active_sensor_update_icon(active_sensor, icon_filename, icon_size, sensor_type);
}
g_object_unref(pixbuf);
}
active_sensor->sensor_value = sensor_value;
old_value_text = value_text;
if (sensor_alarm_enabled) {
switch (sensor_alarm_type) {
case ALARM_WHEN_VALUE_GREATER_THAN_THRESHOLD:
if (sensor_value >= sensor_alarm_value) {
/* make value
* text red with
correct font
size and do
alarm command */
value_text = g_markup_printf_escaped("<span foreground=\"#FF0000\" size=\"%s\">%s</span>", font_size, old_value_text);
active_sensor_alarm_on(active_sensor);
} else {
/* just do font size */
value_text = g_markup_printf_escaped("<span size=\"%s\">%s</span>", font_size, old_value_text);
active_sensor_alarm_off(active_sensor);
}
break;
case ALARM_WHEN_VALUE_LESS_THAN_THRESHOLD:
if (sensor_value <= sensor_alarm_value) {
/* make value
* text red with
correct font
size and do
alarm command */
value_text = g_markup_printf_escaped("<span foreground=\"#FF0000\" size=\"%s\">%s</span>", font_size, old_value_text);
active_sensor_alarm_on(active_sensor);
} else {
/* just do font size */
value_text = g_markup_printf_escaped("<span size=\"%s\">%s</span>", font_size, old_value_text);
active_sensor_alarm_on(active_sensor);
}
break;
default:
g_assert_not_reached();
} /* end
* switch(sensor_alarm_type) */
} else { /* else for if alarm enabled */
/* just do font size */
value_text = g_markup_printf_escaped("<span size=\"%s\">%s</span>", font_size, old_value_text);
active_sensor_alarm_off(active_sensor);
}
g_free(old_value_text);
}
if (active_sensor->value) {
gtk_label_set_markup(active_sensor->value,
value_text);
} else {
active_sensor->value = g_object_new(GTK_TYPE_LABEL,
"use-markup", TRUE,
"label", value_text,
NULL);
}
g_free(value_text);
active_sensor->sensor_value = sensor_value;
/* create label text with font size
* formatting */
label_text = g_markup_printf_escaped("<span size=\"%s\">%s</span>", font_size, sensor_label);
if (active_sensor->label) {
gtk_label_set_markup(active_sensor->label,
label_text);
} else {
active_sensor->label = g_object_new(GTK_TYPE_LABEL,
"use-markup", TRUE,
"label", label_text,
NULL);
}
g_free(label_text);
} else {
g_debug("no get_sensor_value function yet installed for interface.\n");
}
g_free(sensor_path);
g_free(sensor_id);
g_free(sensor_label);
g_free(icon_filename);
} else {
g_debug("Error getting iter when updating sensor...\n");
}
}
/* 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;
gchar *icon_filename;
IconSize icon_size;
g_assert(active_sensor != NULL);
g_assert(sensors_applet != NULL);
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_FILENAME_COLUMN, &icon_filename,
-1);
icon_size = active_sensor_get_icon_size(sensors_applet);
active_sensor_update_icon(active_sensor, icon_filename, icon_size, sensor_type);
g_free(icon_filename);
}
gtk_tree_path_free(path);
}
syntax highlighted by Code2HTML, v. 0.9.1