/* * Copyright (C) 2005 Alex Murray * * 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("%s", font_size, old_value_text); active_sensor_alarm_on(active_sensor); } else { /* just do font size */ value_text = g_markup_printf_escaped("%s", 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("%s", font_size, old_value_text); active_sensor_alarm_on(active_sensor); } else { /* just do font size */ value_text = g_markup_printf_escaped("%s", 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("%s", 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("%s", 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); }