/* * 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 #include #include #include #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 *show_more; GObject *show_less; GObject *ticker; GObject *statusimg; GError *error; int showmore; }; struct gtkui_flash { GtkBuilder *builder; GObject *window; GObject *ssid; GObject *password; GObject *htemp; GObject *mhtemp; GObject *mltemp; GObject *ltemp; GObject *flashdialog; GObject *dialog_ok; GObject *dialog_text; const char *confdata[6]; int close_with_dialog; }; static struct settings settings; static struct gtkui gtkui; static struct gtkui_flash gtkui_flash; static int gtkui_update(void *data); static void gtkui_die(void *data); static int strtokel(const char * const s); void gtkui_togglemore(void); void gtkui_flashwindow_create(void); void gtkui_flashwindow_destroy(void); void gtkui_flashwindow_clean(void); void gtkui_issue_flash_request(void); void gtkui_readhtemp(void); void gtkui_readmhtemp(void); void gtkui_readmltemp(void); void gtkui_readltemp(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(); gtkui.builder = gtk_builder_new_from_file(DATA_DIR "/gtklayout.ui"); 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.show_more = gtk_builder_get_object(gtkui.builder, "show_more"); gtkui.show_less = gtk_builder_get_object(gtkui.builder, "show_less"); gtkui.ticker = gtk_builder_get_object(gtkui.builder, "ticker"); gtkui.statusimg = gtk_builder_get_object(gtkui.builder, "statusimg"); gtk_builder_connect_signals(gtkui.builder, NULL); g_object_unref(G_OBJECT(gtkui.builder)); gtkui.builder = 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 ? statechange : gtk_image_set_from_icon_name(GTK_IMAGE(gtkui.statusimg), "gtk-media-play", GTK_ICON_SIZE_SMALL_TOOLBAR); statechange = 1; } else if (*ret == DEAD && statechange) { gtk_image_set_from_icon_name(GTK_IMAGE(gtkui.statusimg), "gtk-media-pause", GTK_ICON_SIZE_SMALL_TOOLBAR); 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 int strtokel(const char * const s) { int ret; ret = atoi(s); ret += 273; ret *= 10; return ret; } void gtkui_togglemore(void) { gtkui.showmore = !gtkui.showmore; /* this actually switches them around their state */ gtk_widget_set_visible(GTK_WIDGET(gtkui.show_more), !gtkui.showmore); gtk_widget_set_visible(GTK_WIDGET(gtkui.show_less), gtkui.showmore); 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); } void gtkui_flashwindow_create(void) { if (gtkui_flash.window) { goto fail; } gtkui_flash.builder = gtk_builder_new_from_file(DATA_DIR "/gtklayout_flash.ui"); gtkui_flash.window = gtk_builder_get_object(gtkui_flash.builder, "flashwindow"); gtkui_flash.ssid = gtk_builder_get_object(gtkui_flash.builder, "ssid_entry"); gtkui_flash.password = gtk_builder_get_object(gtkui_flash.builder, "pass_entry"); gtkui_flash.htemp = gtk_builder_get_object(gtkui_flash.builder, "htemp_entry"); gtkui_flash.mhtemp = gtk_builder_get_object(gtkui_flash.builder, "mhtemp_entry"); gtkui_flash.mltemp = gtk_builder_get_object(gtkui_flash.builder, "mltemp_entry"); gtkui_flash.ltemp = gtk_builder_get_object(gtkui_flash.builder, "ltemp_entry"); gtkui_flash.flashdialog = gtk_builder_get_object(gtkui_flash.builder, "flashdialog"); gtkui_flash.dialog_ok = gtk_builder_get_object(gtkui_flash.builder, "dialog_ok"); gtkui_flash.dialog_text = gtk_builder_get_object(gtkui_flash.builder, "dialog_text"); gtk_builder_connect_signals(gtkui_flash.builder, NULL); g_object_unref(G_OBJECT(gtkui_flash.builder)); gtkui_flash.builder = NULL; fail: return; } void gtkui_window_destroy(void *window) { gtk_window_close(GTK_WINDOW(window)); } void gtkui_flashwindow_clean(void) { gtkui_flash.window = NULL; } void gtkui_issue_flash_request(void) { static const struct configuration def = {{{ PADDING_START, "ssid", /* ssid */ "password", /* password */ {3330, 3230, 3130, 3030}, /* calibration */ PADDING_END }}}; struct configuration conf; size_t i; size_t len; const char *tmp; gtk_widget_set_visible(GTK_WIDGET(gtkui_flash.flashdialog), 1); for (i = 0; i < sizeof (gtkui_flash.confdata); ++i) { switch (i) { case 0: tmp = gtkui_flash.confdata[i] ? gtkui_flash.confdata[i] : def.ssid; len = strlen(tmp) > (sizeof(conf.ssid) - 1) ? sizeof(conf.ssid) - 1 : strlen(tmp); memcpy(conf.ssid, tmp, len); conf.ssid[len] = '\0'; break; case 1: tmp = gtkui_flash.confdata[i] ? gtkui_flash.confdata[i] : def.password; len = strlen(tmp) > (sizeof(conf.password) - 1) ? sizeof(conf.password) - 1 : strlen(tmp); memcpy(conf.password, tmp, len); conf.password[len] = '\0'; break; case 2: case 3: case 4: case 5: tmp = gtkui_flash.confdata[i] ? (char *) strlen(gtkui_flash.confdata[i]) : NULL; conf.calibration[i - 2] = tmp ? strtokel(gtkui_flash.confdata[i]) : def.calibration[i -2]; break; default: break; } } write_settings(DATA_DIR "/fw.bin", &conf); } void gtkui_readssid(void) { gtkui_flash.confdata[0] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.ssid)); } void gtkui_readpass(void) { gtkui_flash.confdata[1] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.password)); } void gtkui_readhtemp(void) { gtkui_flash.confdata[2] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.htemp)); } void gtkui_readmhtemp(void) { gtkui_flash.confdata[3] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.mhtemp)); } void gtkui_readmltemp(void) { gtkui_flash.confdata[4] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.mltemp)); } void gtkui_readltemp(void) { gtkui_flash.confdata[5] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.ltemp)); } void gtkui_manhandle_flashdialog(void *dialog) { gtk_label_set_markup(GTK_LABEL(gtkui_flash.dialog_text), "Writing to flash... "); if (gtkui_flash.close_with_dialog) { gtk_widget_destroy(GTK_WIDGET(dialog)); /* we also want to close tha parent */ gtk_window_close(GTK_WINDOW(gtkui_flash.window)); } else { gtk_widget_set_visible(GTK_WIDGET(dialog), 0); } } void gtkui_dialog_done(int status) { static const char * const text[2] = {"done", "FAIL"}; static const char * const color[2] = {"#4E9A06", "#EF2929"}; char msg[128]; status = status ? 1 : status; gtkui_flash.close_with_dialog = !status; sprintf(msg, "Writing to flash... %s!", color[status], text[status]); gtk_widget_set_sensitive(GTK_WIDGET(gtkui_flash.dialog_ok), 1); gtk_label_set_markup(GTK_LABEL(gtkui_flash.dialog_text), msg); } void gtkui_update_version(void *about) { extern const char * const version; gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), version); }