make unit of all temperatures selectable
authorPhil Sutter <phil@nwl.cc>
Sun, 7 Dec 2008 19:08:29 +0000 (20:08 +0100)
committerPhil Sutter <phil@nwl.cc>
Mon, 8 Dec 2008 00:45:12 +0000 (01:45 +0100)
This introduces a new configuration variable called "temperature_unit",
specifying the unit of all temperature sensors. To achieve this, each
object outputting a temperature has to call temp_print() like so:
| temp_print(p, p_max_size, <temp val as double>, <unit of val>);
to specify the input temperature unit, either one of the constants
TEMP_CELSIUS or TEMP_FAHRENHEIT.

doc/config_settings.xml
src/Makefile.am
src/conky.c
src/temphelper.c [new file with mode: 0644]
src/temphelper.h [new file with mode: 0644]

index a0c5b8d..760c3fe 100644 (file)
        </varlistentry>
 
        <varlistentry>
+               <term><command><option>temperature_unit</option></command></term>
+               <listitem>
+                       Desired output unit of all objects displaying a temperature.
+                       Parameters are either "fahrenheit" or "celsius". The default
+                       unit is degree Celsius.
+                       <para></para></listitem>
+       </varlistentry>
+
+       <varlistentry>
                <term><command><option>templateN</option></command></term>
                <listitem>
                        Define a template for later use inside TEXT segments. Substitute N by a digit between 0 and 9, inclusively.
index 4ad6a9d..549e6ac 100644 (file)
@@ -126,7 +126,9 @@ conky_SOURCES =             \
        mboxscan.h              \
        $(x11)                  \
        $(xmms2)                \
-       $(smapi)
+       $(smapi)                \
+       temphelper.c            \
+       temphelper.h
 
 conky_LDFLAGS =                                \
        $(PTHREAD_LIBS)                         \
index c340fe1..d4b48b5 100644 (file)
@@ -62,6 +62,8 @@
 
 #include "build.h"
 
+#include "temphelper.h"
+
 #ifndef S_ISSOCK
 #define S_ISSOCK(x)   ((x & S_IFMT) == S_IFSOCK)
 #endif
@@ -1111,7 +1113,6 @@ enum text_object_type {
        OBJ_adt746xfan,
        OBJ_acpifan,
        OBJ_acpitemp,
-       OBJ_acpitempf,
        OBJ_battery,
        OBJ_battery_time,
        OBJ_battery_percent,
@@ -1185,7 +1186,6 @@ enum text_object_type {
        OBJ_i8k_bios,
        OBJ_i8k_serial,
        OBJ_i8k_cpu_temp,
-       OBJ_i8k_cpu_tempf,
        OBJ_i8k_left_fan_status,
        OBJ_i8k_right_fan_status,
        OBJ_i8k_left_fan_rpm,
@@ -2220,7 +2220,6 @@ static void free_text_objects(struct text_object_list *text_object_list, char fu
                switch (obj->type) {
 #ifndef __OpenBSD__
                        case OBJ_acpitemp:
-                       case OBJ_acpitempf:
                                close(obj->data.i);
                                break;
                        case OBJ_i2c:
@@ -2585,8 +2584,6 @@ static struct text_object *construct_text_object(const char *s,
 #else
        OBJ(acpitemp, 0)
                obj->data.i = open_acpi_temperature(arg);
-       END OBJ(acpitempf, 0)
-               obj->data.i = open_acpi_temperature(arg);
        END OBJ(acpiacadapter, 0)
        END OBJ(freq, INFO_FREQ)
 #endif /* !__OpenBSD__ */
@@ -2740,7 +2737,6 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(i8k_bios, INFO_I8K)
        END OBJ(i8k_serial, INFO_I8K)
        END OBJ(i8k_cpu_temp, INFO_I8K)
-       END OBJ(i8k_cpu_tempf, INFO_I8K)
        END OBJ(i8k_left_fan_status, INFO_I8K)
        END OBJ(i8k_right_fan_status, INFO_I8K)
        END OBJ(i8k_left_fan_rpm, INFO_I8K)
@@ -4821,15 +4817,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                ERR("not implemented obj type %d", obj->type);
 #ifndef __OpenBSD__
                        OBJ(acpitemp) {
-                               /* does anyone have decimals in acpi temperature? */
-                               spaced_print(p, p_max_size, "%d", 5, "acpitemp",
-                                               round_to_int(get_acpi_temperature(obj->data.i)));
-                       }
-                       OBJ(acpitempf) {
-                               /* does anyone have decimals in acpi temperature? */
-                               spaced_print(p, p_max_size, "%d", 5, "acpitemp",
-                                               round_to_int((get_acpi_temperature(obj->data.i) + 40) *
-                                                       9.0 / 5 - 40));
+                               temp_print(p, p_max_size, get_acpi_temperature(obj->data.i), TEMP_CELSIUS);
                        }
 #endif /* !__OpenBSD__ */
                        OBJ(freq) {
@@ -5017,13 +5005,10 @@ static void generate_text_internal(char *p, int p_max_size,
                                snprintf(p, p_max_size, "%s", i8k.serial);
                        }
                        OBJ(i8k_cpu_temp) {
-                               snprintf(p, p_max_size, "%s", i8k.cpu_temp);
-                       }
-                       OBJ(i8k_cpu_tempf) {
                                int cpu_temp;
 
                                sscanf(i8k.cpu_temp, "%d", &cpu_temp);
-                               snprintf(p, p_max_size, "%.1f", cpu_temp * (9.0 / 5.0) + 32.0);
+                               temp_print(p, p_max_size, (double)cpu_temp, TEMP_CELSIUS);
                        }
                        OBJ(i8k_left_fan_status) {
                                int left_fan_status;
@@ -5081,7 +5066,8 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        OBJ(ibm_temps) {
                                get_ibm_acpi_temps();
-                               snprintf(p, p_max_size, "%d", ibm_acpi.temps[obj->data.sensor]);
+                               temp_print(p, p_max_size,
+                                          ibm_acpi.temps[obj->data.sensor], TEMP_CELSIUS);
                        }
                        OBJ(ibm_volume) {
                                get_ibm_acpi_volume(p, p_max_size);
@@ -5124,8 +5110,9 @@ static void generate_text_internal(char *p, int p_max_size,
                        OBJ(obsd_sensors_temp) {
                                obsd_sensors.device = sensor_device;
                                update_obsd_sensors();
-                               snprintf(p, p_max_size, "%.1f",
-                                               obsd_sensors.temp[obsd_sensors.device][obj->data.sensor]);
+                               temp_print(p, p_max_size,
+                                          obsd_sensors.temp[obsd_sensors.device][obj->data.sensor],
+                                          TEMP_CELSIUS);
                        }
                        OBJ(obsd_sensors_fan) {
                                obsd_sensors.device = sensor_device;
@@ -5650,10 +5637,16 @@ static void generate_text_internal(char *p, int p_max_size,
                                }
                                if (!obj->data.hddtemp.temp) {
                                        snprintf(p, p_max_size, "N/A");
-                               } else/* if (obj->data.hddtemp.unit == '*')*/ {
-                                       snprintf(p, p_max_size, "%s", obj->data.hddtemp.temp);
-/*                             } else {
-                                       snprintf(p, p_max_size, "%s%c", obj->data.hddtemp.temp, obj->data.hddtemp.unit);*/
+                               } else {
+                                       char *endptr;
+                                       int val = (int)strtol(obj->data.hddtemp.temp, &endptr, 10);
+                                       /* FIXME: review this, it looks broken */
+                                       if (*endptr != '\0' || obj->data.hddtemp.unit == '*')
+                                               snprintf(p, p_max_size, "%s", obj->data.hddtemp.temp);
+                                       else
+                                               temp_print(p, p_max_size, (double)val,
+                                                          ((obj->data.hddtemp.unit == 'C') ?
+                                                           TEMP_CELSIUS : TEMP_FAHRENHEIT));
                                }
                        }
 #endif
@@ -5670,7 +5663,9 @@ static void generate_text_internal(char *p, int p_max_size,
                                r = get_sysfs_info(&obj->data.sysfs.fd, obj->data.sysfs.arg,
                                        obj->data.sysfs.devtype, obj->data.sysfs.type);
 
-                               if (r >= 100.0 || r == 0) {
+                               if (!strncmp(obj->data.sysfs.type, "temp", 4)) {
+                                       temp_print(p, p_max_size, r, TEMP_CELSIUS);
+                               } else if (r >= 100.0 || r == 0) {
                                        snprintf(p, p_max_size, "%d", (int) r);
                                } else {
                                        snprintf(p, p_max_size, "%.1f", r);
@@ -5682,7 +5677,9 @@ static void generate_text_internal(char *p, int p_max_size,
                                r = get_sysfs_info(&obj->data.sysfs.fd, obj->data.sysfs.arg,
                                        obj->data.sysfs.devtype, obj->data.sysfs.type);
 
-                               if (r >= 100.0 || r == 0) {
+                               if (!strncmp(obj->data.sysfs.type, "temp", 4)) {
+                                       temp_print(p, p_max_size, r, TEMP_CELSIUS);
+                               } else if (r >= 100.0 || r == 0) {
                                        snprintf(p, p_max_size, "%d", (int) r);
                                } else {
                                        snprintf(p, p_max_size, "%.1f", r);
@@ -5694,7 +5691,9 @@ static void generate_text_internal(char *p, int p_max_size,
                                r = get_sysfs_info(&obj->data.sysfs.fd, obj->data.sysfs.arg,
                                        obj->data.sysfs.devtype, obj->data.sysfs.type);
 
-                               if (r >= 100.0 || r == 0) {
+                               if (!strncmp(obj->data.sysfs.type, "temp", 4)) {
+                                       temp_print(p, p_max_size, r, TEMP_CELSIUS);
+                               } else if (r >= 100.0 || r == 0) {
                                        snprintf(p, p_max_size, "%d", (int) r);
                                } else {
                                        snprintf(p, p_max_size, "%.1f", r);
@@ -6622,8 +6621,8 @@ head:
                                if(obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) {
                                        val = smapi_bat_installed(idx) ?
                                                smapi_get_bat_int(idx, "temperature") : 0;
-                                       /* temperature is in milli degree celsius, round to degree celsius */
-                                       snprintf(p, p_max_size, "%d", (int)((val / 1000) + 0.5));
+                                       /* temperature is in milli degree celsius */
+                                       temp_print(p, p_max_size, val / 1000, TEMP_CELSIUS);
                                } else
                                        ERR("argument to smapi_bat_temp must be an integer");
                        }
@@ -6685,6 +6684,8 @@ head:
                                int value = get_nvidia_value(obj->data.nvidia.type, display);
                                if(value == -1)
                                        snprintf(p, p_max_size, "N/A");
+                               else if (obj->data.nvidia.type == NV_TEMP)
+                                       temp_print(p, p_max_size, (double)value, TEMP_CELSIUS);
                                else if (obj->data.nvidia.print_as_float &&
                                                value > 0 && value < 100)
                                        snprintf(p, p_max_size, "%.1f", (float)value);
@@ -9088,6 +9089,15 @@ static void load_config_file(const char *f)
                                ifup_strictness = IFUP_UP;
                        }
                }
+
+               CONF("temperature_unit") {
+                       if (!value) {
+                               ERR("config option 'temperature_unit' needs an argument");
+                       } else if (set_temp_output_unit(value)) {
+                               ERR("temperature_unit: incorrect argument");
+                       }
+               }
+
                else {
                        ERR("%s: %d: no such configuration: '%s'", f, line, name);
                }
diff --git a/src/temphelper.c b/src/temphelper.c
new file mode 100644 (file)
index 0000000..b9282ab
--- /dev/null
@@ -0,0 +1,98 @@
+/* temphelper.c:  aid in converting temperature units
+ *
+ * Copyright (C) 2008 Phil Sutter <Phil@nwl.cc>
+ *
+ * This library 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 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA.
+ *
+ * $Id$
+ *
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "temphelper.h"
+
+/* default to output in celsius */
+static enum TEMP_UNIT output_unit = TEMP_CELSIUS;
+
+static double
+fahrenheit_to_celsius(double n)
+{
+       return ((n - 32) * 5 / 9);
+}
+
+static double
+celsius_to_fahrenheit(double n)
+{
+       return ((n * 9 / 5) + 32);
+}
+
+int
+set_temp_output_unit(const char *name)
+{
+       size_t i;
+       int rc = 0;
+       char *buf;
+
+       if (!name)
+               return 1;
+
+       buf = strdup(name);
+       for (i = 0; i < strlen(name); i++)
+               buf[i] = tolower(name[i]);
+
+       if (!strcmp(buf, "celsius"))
+               output_unit = TEMP_CELSIUS;
+       else if (!strcmp(buf, "fahrenheit"))
+               output_unit = TEMP_FAHRENHEIT;
+       else
+               rc = 1;
+       free(buf);
+       return rc;
+}
+
+static double
+convert_temp_output(double n, enum TEMP_UNIT input_unit)
+{
+       if (input_unit == output_unit)
+               return n;
+
+       switch(output_unit) {
+               case TEMP_CELSIUS:
+                       return fahrenheit_to_celsius(n);
+               case TEMP_FAHRENHEIT:
+                       return celsius_to_fahrenheit(n);
+       }
+       /* NOT REACHED */
+       return 0.0;
+}
+
+int temp_print(char *p, size_t p_max_size, double n, enum TEMP_UNIT input_unit)
+{
+       double out, plen;
+
+       out = convert_temp_output(n, input_unit);
+
+       /* Skip decimal for big values but keep padding sane
+        * (i.e. use 4 chars for them)
+        */
+       plen = snprintf(p, p_max_size, ((out > 100.0) ?
+                                       "%4.0lf" : "%2.1lf") , out);
+       return !(plen >= p_max_size);
+}
diff --git a/src/temphelper.h b/src/temphelper.h
new file mode 100644 (file)
index 0000000..b06dc90
--- /dev/null
@@ -0,0 +1,35 @@
+/* temphelper.h:  aid in converting temperature units
+ *
+ * Copyright (C) 2008 Phil Sutter <Phil@nwl.cc>
+ *
+ * This library 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 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef TEMPHELPER_H
+#define TEMPHELPER_H
+
+enum TEMP_UNIT {
+       TEMP_CELSIUS,
+       TEMP_FAHRENHEIT
+};
+
+int set_temp_output_unit(const char *);
+int temp_print(char *, size_t, double, enum TEMP_UNIT);
+
+#endif /* TEMPHELPER_H */