fixed coredump when there are no sensors
[psensor.git] / src / lib / psensor.c
index 76a250d..f8c0a83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2012 jeanfi@gmail.com
+ * Copyright (C) 2010-2014 jeanfi@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
 #include <libintl.h>
 #define _(str) gettext(str)
 
-#include "hdd.h"
-#include "psensor.h"
-#include "lmsensor.h"
+#include <stdio.h>
 
-#ifdef HAVE_GTOP
-#include "cpu.h"
-#endif
+#include <hdd.h>
+#include <psensor.h>
+#include <temperature.h>
 
-
-struct psensor *psensor_create(char *id, char *name,
-                              unsigned int type, int values_max_length)
+struct psensor *psensor_create(char *id,
+                              char *name,
+                              char *chip,
+                              unsigned int type,
+                              int values_max_length)
 {
-       struct psensor *psensor
-           = (struct psensor *)malloc(sizeof(struct psensor));
+       struct psensor *psensor;
+
+       psensor = (struct psensor *)malloc(sizeof(struct psensor));
 
        psensor->id = id;
        psensor->name = name;
-       psensor->enabled = 1;
-       psensor->min = UNKNOWN_DBL_VALUE;
-       psensor->max = UNKNOWN_DBL_VALUE;
+       psensor->chip = chip;
+       psensor->sess_lowest = UNKNOWN_DBL_VALUE;
+       psensor->sess_highest = UNKNOWN_DBL_VALUE;
+
+       if (type & SENSOR_TYPE_PERCENT) {
+               psensor->min = 0;
+               psensor->max = 100;
+       } else {
+               psensor->min = UNKNOWN_DBL_VALUE;
+               psensor->max = UNKNOWN_DBL_VALUE;
+       }
 
        psensor->type = type;
 
        psensor->values_max_length = values_max_length;
        psensor->measures = measures_dbl_create(values_max_length);
 
-       psensor->alarm_enabled = 0;
-       psensor->alarm_high_thresold = 0;
+       psensor->alarm_high_threshold = 0;
+       psensor->alarm_low_threshold = 0;
 
        psensor->cb_alarm_raised = NULL;
        psensor->cb_alarm_raised_data = NULL;
        psensor->alarm_raised = 0;
 
-       psensor->url = NULL;
-
-       psensor->color = NULL;
+       psensor->provider_data = NULL;
+       psensor->provider_data_free_fct = &free;
 
        return psensor;
 }
@@ -74,6 +82,7 @@ void psensor_values_resize(struct psensor *s, int new_size)
 
        if (cur_ms) {
                int i;
+
                for (i = 0; i < new_size - 1 && i < cur_size - 1; i++)
                        measure_copy(&cur_ms[cur_size - i - 1],
                                     &new_ms[new_size - i - 1]);
@@ -85,23 +94,25 @@ void psensor_values_resize(struct psensor *s, int new_size)
        s->measures = new_ms;
 }
 
-void psensor_free(struct psensor *sensor)
+void psensor_free(struct psensor *s)
 {
-       if (sensor) {
-               log_debug("Cleanup %s", sensor->id);
+       if (!s)
+               return;
 
-               free(sensor->name);
-               free(sensor->id);
+       log_debug("Cleanup %s", s->id);
 
-               if (sensor->color)
-                       free(sensor->color);
+       free(s->name);
+       free(s->id);
 
-               measures_free(sensor->measures);
+       if (s->chip)
+               free(s->chip);
 
-               free(sensor->url);
+       measures_free(s->measures);
 
-               free(sensor);
-       }
+       if (s->provider_data && s->provider_data_free_fct)
+               s->provider_data_free_fct(s->provider_data);
+
+       free(s);
 }
 
 void psensor_list_free(struct psensor **sensors)
@@ -141,30 +152,15 @@ int psensor_list_size(struct psensor **sensors)
        return size;
 }
 
-int psensor_list_contains_type(struct psensor **sensors, unsigned int type)
-{
-       struct psensor **s;
-
-       if (!sensors)
-               return 0;
-
-       s = sensors;
-       while (*s) {
-               if ((*s)->type == type)
-                       return 1;
-               s++;
-       }
-
-       return 0;
-}
-
 struct psensor **psensor_list_add(struct psensor **sensors,
                                  struct psensor *sensor)
 {
-       int size = psensor_list_size(sensors);
+       int size;
+       struct psensor **result;
 
-       struct psensor **result
-           = malloc((size + 1 + 1) * sizeof(struct psensor *));
+       size = psensor_list_size(sensors);
+
+       result = malloc((size + 1 + 1) * sizeof(struct psensor *));
 
        if (sensors)
                memcpy(result, sensors, size * sizeof(struct psensor *));
@@ -175,6 +171,22 @@ struct psensor **psensor_list_add(struct psensor **sensors,
        return result;
 }
 
+void psensor_list_append(struct psensor ***sensors, struct psensor *sensor)
+{
+       struct psensor **tmp;
+
+       if (!sensor)
+               return;
+
+       tmp = psensor_list_add(*sensors, sensor);
+
+       if (tmp != *sensors) {
+               free(*sensors);
+               *sensors = tmp;
+       }
+}
+
+
 struct psensor *psensor_list_get_by_id(struct psensor **sensors, const char *id)
 {
        struct psensor **sensors_cur = sensors;
@@ -194,41 +206,22 @@ int is_temp_type(unsigned int type)
        return type & SENSOR_TYPE_TEMP;
 }
 
-int is_fan_type(unsigned int type)
+char *
+psensor_value_to_str(unsigned int type, double value, int use_celsius)
 {
-       return type & SENSOR_TYPE_FAN;
-}
+       char *str;
+       const char *unit;
 
-double celcius_to_fahrenheit(double c)
-{
-       return c * (9.0/5.0) + 32;
-}
+       /*
+        * should not be possible to exceed 20 characters with temp or
+        * rpm values the .x part is never displayed
+        */
+       str = malloc(20);
 
-double fahrenheit_to_celcius(double f)
-{
-       return (f - 32) * (5.0/9.0);
-}
+       unit = psensor_type_to_unit_str(type, use_celsius);
 
-char *
-psensor_value_to_str(unsigned int type, double value, int use_celcius)
-{
-       /* should not be possible to exceed 20 characters with temp or
-          rpm values the .x part is never displayed */
-       char *str = malloc(20);
-
-       char *unit;
-
-       if (is_temp_type(type))
-               if (use_celcius) {
-                       unit = "°C";
-               } else {
-                       unit = "°F";
-                       value = celcius_to_fahrenheit(value);
-               }
-       else if (type & SENSOR_TYPE_CPU_USAGE)
-               unit = "%";
-       else
-               unit = "";
+       if (is_temp_type(type) && !use_celsius)
+               value = celsius_to_fahrenheit(value);
 
        sprintf(str, "%.0f%s", value, unit);
 
@@ -238,9 +231,9 @@ psensor_value_to_str(unsigned int type, double value, int use_celcius)
 char *
 psensor_measure_to_str(const struct measure *m,
                       unsigned int type,
-                      unsigned int use_celcius)
+                      unsigned int use_celsius)
 {
-       return psensor_value_to_str(type, m->value, use_celcius);
+       return psensor_value_to_str(type, m->value, use_celsius);
 }
 
 void psensor_set_current_value(struct psensor *sensor, double value)
@@ -253,9 +246,7 @@ void psensor_set_current_value(struct psensor *sensor, double value)
        psensor_set_current_measure(sensor, value, tv);
 }
 
-void
-psensor_set_current_measure(struct psensor *s,
-                           double v, struct timeval tv)
+void psensor_set_current_measure(struct psensor *s, double v, struct timeval tv)
 {
        memmove(s->measures,
                &s->measures[1],
@@ -264,26 +255,23 @@ psensor_set_current_measure(struct psensor *s,
        s->measures[s->values_max_length - 1].value = v;
        s->measures[s->values_max_length - 1].time = tv;
 
-       if (s->min == UNKNOWN_DBL_VALUE || v < s->min)
-               s->min = v;
+       if (s->sess_lowest == UNKNOWN_DBL_VALUE || v < s->sess_lowest)
+               s->sess_lowest = v;
 
-       if (s->max == UNKNOWN_DBL_VALUE || v > s->max)
-               s->max = v;
+       if (s->sess_highest == UNKNOWN_DBL_VALUE || v > s->sess_highest)
+               s->sess_highest = v;
 
-       if (s->alarm_enabled) {
-               if (v > s->alarm_high_thresold) {
-                       if (!s->alarm_raised && s->cb_alarm_raised)
-                               s->cb_alarm_raised(s,
-                                                  s->cb_alarm_raised_data);
-
-                       s->alarm_raised = 1;
-               } else {
-                       s->alarm_raised = 0;
+       if (v > s->alarm_high_threshold || v < s->alarm_low_threshold) {
+               if (!s->alarm_raised && s->cb_alarm_raised) {
+                       s->alarm_raised = true;
+                       s->cb_alarm_raised(s, s->cb_alarm_raised_data);
                }
+       } else {
+               s->alarm_raised = false;
        }
 }
 
-double psensor_get_current_value(struct psensor *sensor)
+double psensor_get_current_value(const struct psensor *sensor)
 {
        return sensor->measures[sensor->values_max_length - 1].value;
 }
@@ -294,10 +282,10 @@ struct measure *psensor_get_current_measure(struct psensor *sensor)
 }
 
 /*
-  Returns the minimal value of a given 'type' (SENSOR_TYPE_TEMP or
-  SENSOR_TYPE_FAN)
* Returns the minimal value of a given 'type' (SENSOR_TYPE_TEMP or
* SENSOR_TYPE_FAN)
  */
-double get_min_value(struct psensor **sensors, int type)
+static double get_min_value(struct psensor **sensors, int type)
 {
        double m = UNKNOWN_DBL_VALUE;
        struct psensor **s = sensors;
@@ -305,7 +293,7 @@ double get_min_value(struct psensor **sensors, int type)
        while (*s) {
                struct psensor *sensor = *s;
 
-               if (sensor->enabled && (sensor->type & type)) {
+               if (sensor->type & type) {
                        int i;
                        double t;
 
@@ -326,8 +314,8 @@ double get_min_value(struct psensor **sensors, int type)
 }
 
 /*
-  Returns the maximal value of a given 'type' (SENSOR_TYPE_TEMP or
-  SENSOR_TYPE_FAN)
* Returns the maximal value of a given 'type' (SENSOR_TYPE_TEMP or
* SENSOR_TYPE_FAN)
  */
 double get_max_value(struct psensor **sensors, int type)
 {
@@ -337,9 +325,10 @@ double get_max_value(struct psensor **sensors, int type)
        while (*s) {
                struct psensor *sensor = *s;
 
-               if (sensor->enabled && (sensor->type & type)) {
+               if (sensor->type & type) {
                        int i;
                        double t;
+
                        for (i = 0; i < sensor->values_max_length; i++) {
                                t = sensor->measures[i].value;
 
@@ -356,28 +345,6 @@ double get_max_value(struct psensor **sensors, int type)
        return m;
 }
 
-double
-psensor_get_max_current_value(struct psensor **sensors, unsigned int type)
-{
-       double m = UNKNOWN_DBL_VALUE;
-       struct psensor **s_cur = sensors;
-
-       while (*s_cur) {
-               struct psensor *s = *s_cur;
-
-               if (s->enabled && (s->type & type)) {
-                       double v = psensor_get_current_value(s);
-
-                       if (m == UNKNOWN_DBL_VALUE || v > m)
-                               m = v;
-               }
-
-               s_cur++;
-       }
-
-       return m;
-}
-
 double get_min_temp(struct psensor **sensors)
 {
        return get_min_value(sensors, SENSOR_TYPE_TEMP);
@@ -398,109 +365,77 @@ double get_max_temp(struct psensor **sensors)
        return get_max_value(sensors, SENSOR_TYPE_TEMP);
 }
 
-struct psensor **get_all_sensors(int use_libatasmart, int values_max_length)
+const char *psensor_type_to_str(unsigned int type)
 {
-       struct psensor **psensors = NULL;
-       struct psensor **tmp_psensors;
-
-       psensors = lmsensor_psensor_list_add(NULL, values_max_length);
-
-       if (!use_libatasmart) {
-               tmp_psensors = hddtemp_psensor_list_add(psensors,
-                                                       values_max_length);
-               if (tmp_psensors != psensors) {
-                       free(psensors);
-                       psensors = tmp_psensors;
-               }
+       if (type & SENSOR_TYPE_NVCTRL) {
+               if (type & SENSOR_TYPE_TEMP)
+                       return "Temperature";
+               else if (type & SENSOR_TYPE_GRAPHICS)
+                       return "Graphics usage";
+               else if (type & SENSOR_TYPE_VIDEO)
+                       return "Video usage";
+               else if (type & SENSOR_TYPE_MEMORY)
+                       return "Memory usage";
+               else if (type & SENSOR_TYPE_PCIE)
+                       return "PCIe usage";
+
+               return "NVIDIA GPU";
        }
-#ifdef HAVE_ATASMART
-               else {
-                       tmp_psensors = hdd_psensor_list_add(psensors,
-                                                           values_max_length);
-                       if (tmp_psensors != psensors) {
-                               free(psensors);
-                               psensors = tmp_psensors;
-                       }
-               }
-#endif
 
-       if (!psensors) {        /* there is no detected sensors */
-               psensors = malloc(sizeof(struct psensor *));
-               *psensors = NULL;
+       if (type & SENSOR_TYPE_ATIADL) {
+               if (type & SENSOR_TYPE_TEMP)
+                       return "AMD GPU Temperature";
+               else if (type & SENSOR_TYPE_RPM)
+                       return "AMD GPU Fan Speed";
+               /*else type & SENSOR_TYPE_USAGE */
+               return "AMD GPU Usage";
        }
 
-       return psensors;
-}
-
-const char *psensor_type_to_str(unsigned int type)
-{
-       if ((type & SENSOR_TYPE_NVIDIA_TEMP) == SENSOR_TYPE_NVIDIA_TEMP)
-               return "NVidia GPU Temperature";
-
-       if ((type & SENSOR_TYPE_AMD_TEMP) == SENSOR_TYPE_AMD_TEMP)
-               return "AMD GPU Temperature";
-
-       if ((type & SENSOR_TYPE_AMD_FAN) == SENSOR_TYPE_AMD_FAN)
-               return "AMD GPU Fan Speed";
-
        if ((type & SENSOR_TYPE_HDD_TEMP) == SENSOR_TYPE_HDD_TEMP)
                return "HDD Temperature";
 
-       if (type & SENSOR_TYPE_CPU_USAGE)
+       if ((type & SENSOR_TYPE_CPU_USAGE) == SENSOR_TYPE_CPU_USAGE)
                return "CPU Usage";
 
        if (type & SENSOR_TYPE_TEMP)
                return "Temperature";
 
-       if (type & SENSOR_TYPE_FAN)
+       if (type & SENSOR_TYPE_RPM)
                return "Fan";
 
+       if (type & SENSOR_TYPE_CPU)
+               return "CPU";
+
        if (type & SENSOR_TYPE_REMOTE)
                return "Remote";
 
-       return "N/A";           /* should not be possible */
+       if (type & SENSOR_TYPE_MEMORY)
+               return "Memory";
+
+       return "N/A";
 }
 
 
-const char *psensor_type_to_unit_str(unsigned int type, int use_celcius)
+const char *psensor_type_to_unit_str(unsigned int type, int use_celsius)
 {
-       if (type & SENSOR_TYPE_TEMP) {
-               if (use_celcius)
+       if (is_temp_type(type)) {
+               if (use_celsius)
                        return "\302\260C";
-               else
-                       return "\302\260F";
-       }
-
-       if (type & SENSOR_TYPE_FAN)
+               return "\302\260F";
+       } else if (type & SENSOR_TYPE_RPM) {
                return _("RPM");
-
-       if (type & SENSOR_TYPE_CPU_USAGE)
+       } else if (type & SENSOR_TYPE_PERCENT) {
                return _("%");
-
+       }
        return _("N/A");
 }
 
-void psensor_list_update_measures(struct psensor **sensors)
-{
-       lmsensor_psensor_list_update(sensors);
-
-#ifdef HAVE_GTOP
-       cpu_psensor_list_update(sensors);
-#endif
-
-       if (psensor_list_contains_type(sensors, SENSOR_TYPE_HDD_TEMP_HDDTEMP))
-               hddtemp_psensor_list_update(sensors);
-
-#ifdef HAVE_ATASMART
-       if (psensor_list_contains_type(sensors,
-                                      SENSOR_TYPE_HDD_TEMP_ATASMART))
-               hdd_psensor_list_update(sensors);
-#endif
-}
-
 void psensor_log_measures(struct psensor **sensors)
 {
-       if (log_level == LOG_DEBUG)
+       if (log_level == LOG_DEBUG) {
+               if (!sensors)
+                       return;
+
                while (*sensors) {
                        log_debug("Measure: %s %.2f",
                                   (*sensors)->name,
@@ -508,14 +443,27 @@ void psensor_log_measures(struct psensor **sensors)
 
                        sensors++;
                }
+       }
 }
 
-void psensor_init()
+struct psensor **psensor_list_copy(struct psensor **sensors)
 {
-       lmsensor_init();
+       struct psensor **result;
+       int n, i;
+
+       n = psensor_list_size(sensors);
+       result = malloc((n+1) * sizeof(struct psensor *));
+       for (i = 0; i < n; i++)
+               result[i] = sensors[i];
+       result[n] = NULL;
+
+       return result;
 }
 
-void psensor_cleanup()
+char *
+psensor_current_value_to_str(const struct psensor *s, unsigned int use_celsius)
 {
-       lmsensor_cleanup();
+       return psensor_value_to_str(s->type,
+                                   psensor_get_current_value(s),
+                                   use_celsius);
 }