]>
Commit | Line | Data |
---|---|---|
1 | // For vasprintf | |
2 | #define _GNU_SOURCE | |
3 | ||
4 | #include "chart.h" | |
5 | #include <ctype.h> | |
6 | #include <errno.h> | |
7 | #include <gtk/gtk.h> | |
8 | #include <math.h> | |
9 | #include <stdarg.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | ||
13 | char *sasprintf(const char *fmt, ...) { | |
14 | char *result; | |
15 | va_list args; | |
16 | va_start(args, fmt); | |
17 | if (vasprintf(&result, fmt, args) == -1) { | |
18 | fprintf(stderr, "Can't allocate memory!?\n"); | |
19 | abort(); | |
20 | } | |
21 | va_end(args); | |
22 | return result; | |
23 | } | |
24 | ||
25 | struct State { | |
26 | char *voltage_filename; | |
27 | char *current_filename; | |
28 | BVChart *voltage; | |
29 | BVChart *current; | |
30 | }; | |
31 | ||
32 | static float fatof(const char *filename) { | |
33 | FILE *f = fopen(filename, "r"); | |
34 | if (f == NULL) { | |
35 | return NAN; | |
36 | } | |
37 | ||
38 | const int bufsize = 1024; | |
39 | char buf[bufsize]; | |
40 | const int read = fread(buf, sizeof(char), bufsize, f); | |
41 | if (read == 0 || read == bufsize || ferror(f)) { | |
42 | fclose(f); | |
43 | return NAN; | |
44 | } | |
45 | fclose(f); | |
46 | ||
47 | char *end; | |
48 | errno = 0; | |
49 | float val = strtof(buf, &end); | |
50 | int parsed = end - buf; | |
51 | gboolean parsed_all = parsed == read; | |
52 | gboolean parsed_all_but_space = parsed == read - 1 && isspace(*end); | |
53 | gboolean parse_ok = parsed_all || parsed_all_but_space; | |
54 | if (errno != 0 || parsed == 0 || !parse_ok) { | |
55 | return NAN; | |
56 | } | |
57 | return val; | |
58 | } | |
59 | ||
60 | static gboolean collect_data(struct State *state) { | |
61 | fprintf(stderr, "Voltage: %f, current: %f\n", fatof(state->voltage_filename), | |
62 | fatof(state->current_filename)); | |
63 | return TRUE; | |
64 | } | |
65 | ||
66 | static void activate(GtkApplication *app, gpointer user_data) { | |
67 | ||
68 | GtkWidget *window = gtk_application_window_new(app); | |
69 | gtk_window_set_title(GTK_WINDOW(window), "BatteryViewer"); | |
70 | gtk_window_set_default_size(GTK_WINDOW(window), 200, 200); | |
71 | ||
72 | GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1); | |
73 | gtk_container_add(GTK_CONTAINER(window), box); | |
74 | ||
75 | struct State *state = (struct State *)user_data; | |
76 | state->voltage = BV_CHART(bv_chart_new()); | |
77 | bv_chart_add_point(state->voltage, 0.0, 0.0); | |
78 | bv_chart_add_point(state->voltage, 1.0, 1.0); | |
79 | bv_chart_add_point(state->voltage, 3.0, 2.0); | |
80 | gboolean expand = TRUE; | |
81 | gboolean fill = TRUE; | |
82 | guint padding = 0; | |
83 | gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(state->voltage), expand, fill, | |
84 | padding); | |
85 | ||
86 | state->current = BV_CHART(bv_chart_new()); | |
87 | bv_chart_add_point(state->current, 0.0, 1.0); | |
88 | bv_chart_add_point(state->current, 1.0, 0.0); | |
89 | gtk_box_pack_end(GTK_BOX(box), GTK_WIDGET(state->current), expand, fill, | |
90 | padding); | |
91 | ||
92 | gtk_widget_show_all(window); | |
93 | ||
94 | g_timeout_add_seconds(1, (GSourceFunc)collect_data, user_data); | |
95 | } | |
96 | ||
97 | int main(int argc, char **argv) { | |
98 | char *battery_dir = "/sys/class/power_supply/BAT0"; | |
99 | struct State state = { | |
100 | .voltage_filename = sasprintf("%s/voltage_now", battery_dir), | |
101 | .current_filename = sasprintf("%s/current_now", battery_dir), | |
102 | }; | |
103 | ||
104 | GtkApplication *app = gtk_application_new("com.scottworley.batteryviewer", | |
105 | G_APPLICATION_DEFAULT_FLAGS); | |
106 | g_signal_connect(app, "activate", G_CALLBACK(activate), &state); | |
107 | int status = g_application_run(G_APPLICATION(app), argc, argv); | |
108 | g_object_unref(app); | |
109 | ||
110 | return status; | |
111 | } |