diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/gtk.c | 149 | ||||
-rw-r--r-- | src/server/gtk.h | 27 | ||||
-rw-r--r-- | src/server/gtklayout.ui | 127 | ||||
-rw-r--r-- | src/server/main.c | 36 | ||||
-rw-r--r-- | src/server/ui.c | 7 | ||||
-rw-r--r-- | src/server/ui.h | 2 | ||||
-rw-r--r-- | src/server/util.h | 2 |
7 files changed, 337 insertions, 13 deletions
diff --git a/src/server/gtk.c b/src/server/gtk.c new file mode 100644 index 0000000..8b850cf --- /dev/null +++ b/src/server/gtk.c @@ -0,0 +1,149 @@ +/* + * Hot Beverage Companion – desktop application gtk ui + * + * Copyright (C) 2018 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#include <gtk/gtk.h> +#include <time.h> +#include <string.h> +#include "util.h" +#include "gtk.h" + +struct settings { + int nd; + struct timespec period; +}; + +struct gtkui { + GtkBuilder *builder; + GObject *window; + GObject *tempvalue; + GObject *resistance; + GObject *voltage; + GObject *reslabel; + GObject *voltlabel; + GObject *showmorebutton; + GObject *button_on; + GObject *button_off; + GObject *ticker; + GError *error; + int showmore; +}; + +static struct settings settings; +static struct gtkui gtkui; + +static int gtkui_update(void *data); +static void gtkui_die(void *data); +static void gtkui_togglemore(void); + +int gtkui_init(int *argc, char ***argv, int nd, struct timespec period) +{ + int ret = A_OK; + + settings.nd = nd; + settings.period = period; + + if (!gtk_init_check(argc, argv)) { + ret = ERROR; + goto fail; + } + + gtkui.builder = gtk_builder_new(); + + if (!gtk_builder_add_from_file(gtkui.builder, "gtklayout.ui", >kui.error)) { + ret = ERROR; + goto fail; + } + + gtkui.window = gtk_builder_get_object(gtkui.builder, "window"); + gtkui.tempvalue = gtk_builder_get_object(gtkui.builder, "tempvalue"); + gtkui.resistance = gtk_builder_get_object(gtkui.builder, "resistance"); + gtkui.voltage = gtk_builder_get_object(gtkui.builder, "voltage"); + gtkui.reslabel = gtk_builder_get_object(gtkui.builder, "reslabel"); + gtkui.voltlabel = gtk_builder_get_object(gtkui.builder, "voltlabel"); + gtkui.showmorebutton = gtk_builder_get_object(gtkui.builder, "showmore"); + gtkui.button_on = gtk_builder_get_object(gtkui.builder, "button_on"); + gtkui.button_off = gtk_builder_get_object(gtkui.builder, "button_off"); + gtkui.ticker = gtk_builder_get_object(gtkui.builder, "ticker"); + g_signal_connect(gtkui.window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect(gtkui.showmorebutton, "toggled", G_CALLBACK(gtkui_togglemore), NULL); + gtkui.showmore = 1; /* we are setting this so we can toggle this off on the following call */ + gtkui_togglemore(); + +fail: + return ret; +} +int gtkui_loop(void) +{ + int ret; + g_timeout_add_full(G_PRIORITY_DEFAULT, settings.period.tv_nsec / (1000 * 1000), gtkui_update, &ret, gtkui_die); + gtk_main(); + + return ret; +} + +static int gtkui_update(void *data) +{ + static const char ticker[] = "|/-\\"; + static const char waitmsg[] = "Waiting."; + static int statechange = 1; + static struct tempmodule_state state; + char textbuf[32]; + int *ret; + + ret = data; + *ret = refresh_data(settings.nd, &state); + if (*ret == A_OK) { + textbuf[0] = ticker[state.sequence % strlen(ticker)]; + textbuf[1] = '\0'; + gtk_label_set_text(GTK_LABEL(gtkui.ticker), textbuf); + sprintf(textbuf, "%.1f°C", state.temperature); + gtk_label_set_text(GTK_LABEL(gtkui.tempvalue), textbuf); + sprintf(textbuf, "%hdΩ", state.resistance); + gtk_label_set_text(GTK_LABEL(gtkui.resistance), textbuf); + sprintf(textbuf, "%.3fV", state.voltage); + gtk_label_set_text(GTK_LABEL(gtkui.voltage), textbuf); + statechange = 1; + } else if (*ret == DEAD && statechange) { + gtk_label_set_text(GTK_LABEL(gtkui.tempvalue), waitmsg); + gtk_label_set_text(GTK_LABEL(gtkui.resistance), waitmsg); + gtk_label_set_text(GTK_LABEL(gtkui.voltage), waitmsg); + statechange = 0; + } + + return *ret != ERROR; +} + +static void gtkui_die(void *data) +{ + (void) data; /* silence unused variable warning */ + gtk_main_quit(); + return; +} + +static void gtkui_togglemore(void) +{ + gtkui.showmore = !gtkui.showmore; + gtkui.showmore ? gtk_button_set_image(GTK_BUTTON(gtkui.showmorebutton), GTK_WIDGET(gtkui.button_on)) : + gtk_button_set_image(GTK_BUTTON(gtkui.showmorebutton), GTK_WIDGET(gtkui.button_off)); + gtk_widget_set_visible (GTK_WIDGET(gtkui.resistance), gtkui.showmore); + gtk_widget_set_visible (GTK_WIDGET(gtkui.voltage), gtkui.showmore); + gtk_widget_set_visible (GTK_WIDGET(gtkui.reslabel), gtkui.showmore); + gtk_widget_set_visible (GTK_WIDGET(gtkui.voltlabel), gtkui.showmore); +} diff --git a/src/server/gtk.h b/src/server/gtk.h new file mode 100644 index 0000000..d2b716a --- /dev/null +++ b/src/server/gtk.h @@ -0,0 +1,27 @@ +/* + * Hot Beverage Companion – desktop application gtk ui + * + * Copyright (C) 2018 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#ifndef GTK_H_INCLUDED +#define GTK_H_INCLUDED + +int gtkui_init(int *argc, char ***argv, int nd, struct timespec period); +int gtkui_loop(void); + +#endif /* GTK_H_INCLUDED */ diff --git a/src/server/gtklayout.ui b/src/server/gtklayout.ui new file mode 100644 index 0000000..69fd947 --- /dev/null +++ b/src/server/gtklayout.ui @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.20.0 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkImage" id="button_off"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-no</property> + </object> + <object class="GtkImage" id="button_on"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-yes</property> + </object> + <object class="GtkWindow" id="window"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="title" translatable="yes">Coffeetemp</property> + <property name="resizable">False</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="ticker"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"> Temperature: </property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="tempvalue"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="showmore"> + <property name="label" translatable="yes">show all</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="image">button_on</property> + <property name="always_show_image">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="reslabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"> Resistence: </property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="resistance"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="voltage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="voltlabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"> Voltage: </property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + </object> +</interface> diff --git a/src/server/main.c b/src/server/main.c index e75929c..11f4a59 100644 --- a/src/server/main.c +++ b/src/server/main.c @@ -40,11 +40,11 @@ struct settings { unsigned short int port; }; -static int init(int argc, char ***argv, const struct settings * const settings); +static int init(int *argc, char ***argv, const struct settings * const settings); static struct settings parseargs(int argc, char **argv); -static enum uitype identify_ui(const char * const s); +static enum uitype identify_ui(const char * const s, const char * const name); static struct timespec calc_period(const char * const s); -static size_t printhelp(const char * const name); +static size_t printhelp(const char * const name) __attribute__((noreturn)); int main(int argc, char **argv) { @@ -53,7 +53,7 @@ int main(int argc, char **argv) int nd; settings = parseargs(argc, argv); - nd = init(argc, &argv, &settings); + nd = init(&argc, &argv, &settings); if (nd == ERROR) { ret = nd; @@ -66,7 +66,7 @@ fail: return ret; } -static int init(int argc, char ***argv, const struct settings * const settings) +static int init(int *argc, char ***argv, const struct settings * const settings) { int ret = A_OK; int nd; @@ -104,7 +104,7 @@ static struct settings parseargs(int argc, char **argv) if (!(strncmp(argv[i], "--period=", 8))) { ret.period = strlen(argv[i]) > 9 ? calc_period(argv[i] + 9) : (struct timespec) {0, printhelp(*argv)}; } else if (!(strncmp(argv[i], "--ui=", 5))) { - ret.ui = strlen(argv[i]) > 5 ? identify_ui(argv[i] + 5) : printhelp(*argv); + ret.ui = strlen(argv[i]) > 5 ? identify_ui(argv[i] + 5, *argv) : printhelp(*argv); } else if (!(strncmp(argv[i], "--port=", 7))) { ret.port = strlen(argv[i]) > 7 ? strtoul(argv[i] + 7, NULL, 10) : printhelp(*argv); } else { @@ -115,10 +115,28 @@ static struct settings parseargs(int argc, char **argv) return ret; } -static enum uitype identify_ui(const char * const s) +static enum uitype identify_ui(const char * const s, const char * const name) { - /* TODO: stub! */ - return ui_curses; + static const struct uituple { + char *name; + enum uitype type; + } uilist[] = {{"none", ui_none}, {"file", ui_file}, {"curses", ui_curses}, {"gtk", ui_gtk}}; + size_t i; + int found = 0; + enum uitype ret = ui_none; + + for (i = 0; i < arrsize(uilist); ++i) { + if (!strcmp(s, uilist[i].name)) { + found = 1; + ret = uilist[i].type; + } + } + + if (!found) { + printhelp(name); + } + + return ret; } static struct timespec calc_period(const char * const s) diff --git a/src/server/ui.c b/src/server/ui.c index 7412a91..62cfc1c 100644 --- a/src/server/ui.c +++ b/src/server/ui.c @@ -21,10 +21,11 @@ #include "util.h" #include "ui.h" #include "curses.h" +#include "gtk.h" static enum uitype chosen = ui_none; -int ui_init(int argc, char ***argv, enum uitype ui, int nd, struct timespec period) +int ui_init(int *argc, char ***argv, enum uitype ui, int nd, struct timespec period) { int ret = A_OK; @@ -41,7 +42,7 @@ int ui_init(int argc, char ***argv, enum uitype ui, int nd, struct timespec peri ret = curses_init(nd, period); break; case ui_gtk: - /* ret = gtkui_init(nd, period); */ + ret = gtkui_init(argc, argv, nd, period); break; default: /* noop */ @@ -66,7 +67,7 @@ int ui_startloop(void) ret = curses_loop(); break; case ui_gtk: - /* ret = gtkui_loop(); */ + ret = gtkui_loop(); break; default: /* noop */ diff --git a/src/server/ui.h b/src/server/ui.h index d764180..1f22243 100644 --- a/src/server/ui.h +++ b/src/server/ui.h @@ -30,7 +30,7 @@ enum uitype { ui_gtk }; -int ui_init(int argc, char ***argv, enum uitype ui, int nd, struct timespec period); +int ui_init(int *argc, char ***argv, enum uitype ui, int nd, struct timespec period); int ui_startloop(void); #endif /* UI_H_INCLUDED */ diff --git a/src/server/util.h b/src/server/util.h index 80e81cf..9c0f907 100644 --- a/src/server/util.h +++ b/src/server/util.h @@ -21,6 +21,8 @@ #ifndef UTIL_H_INCLUDED #define UTIL_H_INCLUDED +#define arrsize(a) (sizeof(a)/sizeof(*a)) + enum response { ERROR = -1, A_OK = 0, |