summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorGravatar Gediminas Jakutis <gediminas@varciai.lt> 2018-05-08 23:56:30 +0300
committerGravatar Gediminas Jakutis <gediminas@varciai.lt> 2018-05-08 23:56:30 +0300
commitba43745c2b8a764088a3bf39485849c0ec64a1ac (patch)
treea07edfdc0221c4a7e0e7824c215c9702e5e8f7cd /src/server
parent92c7163d6c0ddf0ffb958db5528ee35bb0460293 (diff)
downloadcoffeetemp-ba43745c2b8a764088a3bf39485849c0ec64a1ac.tar.gz
coffeetemp-ba43745c2b8a764088a3bf39485849c0ec64a1ac.tar.bz2
coffeetemp-ba43745c2b8a764088a3bf39485849c0ec64a1ac.zip
server: add an initial GTK UI front-end.
Diffstat (limited to 'src/server')
-rw-r--r--src/server/gtk.c149
-rw-r--r--src/server/gtk.h27
-rw-r--r--src/server/gtklayout.ui127
-rw-r--r--src/server/main.c36
-rw-r--r--src/server/ui.c7
-rw-r--r--src/server/ui.h2
-rw-r--r--src/server/util.h2
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", &gtkui.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,