diff options
author | Keith Packard <keithp@keithp.com> | 2009-05-17 00:13:45 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2009-05-17 00:13:45 -0700 |
commit | be3f4fed7b863c8cdaabe32b61b65a8b3cd11355 (patch) | |
tree | c60a999a6abc8061492b7cdddd141353e8768700 | |
parent | 93d7ce8e054515ed7b166eb042ae7f47e564d21d (diff) |
Add lots more aoview UI bits
Logs data to files, displays current state in window.
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | aoview/.gitignore | 2 | ||||
-rw-r--r-- | aoview/Makefile | 7 | ||||
-rw-r--r-- | aoview/aoview.glade | 301 | ||||
-rw-r--r-- | aoview/aoview.h | 44 | ||||
-rw-r--r-- | aoview/aoview_dev.c | 41 | ||||
-rw-r--r-- | aoview/aoview_dev_dialog.c | 26 | ||||
-rw-r--r-- | aoview/aoview_log.c | 192 | ||||
-rw-r--r-- | aoview/aoview_main.c | 4 | ||||
-rw-r--r-- | aoview/aoview_monitor.c | 9 | ||||
-rw-r--r-- | aoview/aoview_state.c | 43 | ||||
-rw-r--r-- | aoview/aoview_table.c | 62 | ||||
-rw-r--r-- | aoview/aoview_util.c | 91 |
12 files changed, 583 insertions, 239 deletions
diff --git a/aoview/.gitignore b/aoview/.gitignore new file mode 100644 index 00000000..03c0c7da --- /dev/null +++ b/aoview/.gitignore @@ -0,0 +1,2 @@ +*.o +aoview diff --git a/aoview/Makefile b/aoview/Makefile index bdf7853c..253a160e 100644 --- a/aoview/Makefile +++ b/aoview/Makefile @@ -1,4 +1,4 @@ -MODULES=gtk+-2.0 libglade-2.0 +MODULES=gtk+-2.0 libglade-2.0 gconf-2.0 INCLUDES=$(shell pkg-config --cflags $(MODULES)) -I.. WARN= -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -fno-strict-aliasing CFLAGS=$(INCLUDES) -O0 -g $(WARN) @@ -11,7 +11,10 @@ SRC = \ aoview_serial.c \ aoview_monitor.c \ aoview_state.c \ - aoview_convert.c + aoview_convert.c \ + aoview_log.c \ + aoview_table.c \ + aoview_util.c INC = \ aoview.h diff --git a/aoview/aoview.glade b/aoview/aoview.glade index e60f17f7..4b1566dc 100644 --- a/aoview/aoview.glade +++ b/aoview/aoview.glade @@ -159,6 +159,47 @@ </widget> </child> <child> + <widget class="GtkMenuItem" id="menuitem5"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Log</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menu5"> + <property name="visible">True</property> + <child> + <widget class="GtkImageMenuItem" id="ao_log_new"> + <property name="label" translatable="yes">_New log</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <child internal-child="image"> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="stock">gtk-new</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="ao_log_configure"> + <property name="label" translatable="yes">_Configure Log</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <signal name="activate" handler="gtk_widget_show" object="log_chooser_dialog" after="yes"/> + <child internal-child="image"> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-preferences</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> <widget class="GtkMenuItem" id="menuitem4"> <property name="visible">True</property> <property name="label" translatable="yes">_Help</property> @@ -185,166 +226,12 @@ </packing> </child> <child> - <widget class="GtkTable" id="table1"> + <widget class="GtkTreeView" id="dataview"> <property name="visible">True</property> - <property name="n_rows">7</property> - <property name="n_columns">2</property> - <child> - <widget class="GtkLabel" id="altitude_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Altitude</property> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="label" translatable="yes">Velocity</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="label" translatable="yes">Acceleration</property> - </widget> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="label" translatable="yes">Latitude</property> - </widget> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="label" translatable="yes">Longitude</property> - </widget> - <packing> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label6"> - <property name="visible">True</property> - <property name="label" translatable="yes">Range</property> - </widget> - <packing> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="label" translatable="yes">Direction</property> - </widget> - <packing> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="altitude_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">0m</property> - <property name="selectable">True</property> - <property name="single_line_mode">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="vel_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">150m/s</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="accel_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">50m/s²</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="lat_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">45° 31' 24''</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="lon_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">122° 40' 34''W</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="range_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">500m</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="direction_value"> - <property name="visible">True</property> - <property name="label" translatable="yes">45°</property> - <property name="selectable">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - </packing> - </child> + <property name="can_focus">True</property> + <property name="headers_clickable">False</property> + <property name="show_expanders">False</property> + <property name="enable_grid_lines">both</property> </widget> <packing> <property name="position">1</property> @@ -385,13 +272,15 @@ <property name="visible">True</property> <property name="layout_style">end</property> <child> - <widget class="GtkButton" id="connect_button"> - <property name="label" translatable="yes">gtk-connect</property> + <widget class="GtkButton" id="cancel_button"> + <property name="label" translatable="yes">gtk-cancel</property> + <property name="response_id">1</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_underline">True</property> <property name="use_stock">True</property> + <signal name="clicked" handler="gtk_widget_hide" object="device_connect_dialog" after="yes"/> </widget> <packing> <property name="expand">False</property> @@ -400,15 +289,70 @@ </packing> </child> <child> - <widget class="GtkButton" id="cancel_button"> + <widget class="GtkButton" id="connect_button"> + <property name="label" translatable="yes">gtk-connect</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkFileChooserDialog" id="log_chooser_dialog"> + <property name="border_width">5</property> + <property name="title" translatable="yes">Configure Log Directory</property> + <property name="type_hint">dialog</property> + <property name="has_separator">False</property> + <property name="action">select-folder</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <widget class="GtkButton" id="log_configure_cancel"> <property name="label" translatable="yes">gtk-cancel</property> - <property name="response_id">1</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <property name="use_underline">True</property> <property name="use_stock">True</property> - <signal name="clicked" handler="gtk_widget_hide" object="device_connect_dialog" after="yes"/> + <signal name="clicked" handler="gtk_widget_hide" object="log_chooser_dialog"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="log_configure_ok"> + <property name="label" translatable="yes">gtk-ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> </widget> <packing> <property name="expand">False</property> @@ -426,4 +370,31 @@ </widget> </child> </widget> + <widget class="GtkMessageDialog" id="log_fail_dialog"> + <property name="border_width">5</property> + <property name="type">popup</property> + <property name="type_hint">normal</property> + <property name="skip_taskbar_hint">True</property> + <property name="message_type">error</property> + <property name="buttons">close</property> + <property name="text">Cannot create log file</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox4"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area4"> + <property name="visible">True</property> + <property name="layout_style">end</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> </glade-interface> diff --git a/aoview/aoview.h b/aoview/aoview.h index 028b2f16..a3214128 100644 --- a/aoview/aoview.h +++ b/aoview/aoview.h @@ -18,8 +18,7 @@ #ifndef _AOVIEW_H_ #define _AOVIEW_H_ -#include <gtk/gtk.h> -#include <glade/glade.h> +#define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> @@ -33,6 +32,10 @@ #include <sys/stat.h> #include <assert.h> +#include <gtk/gtk.h> +#include <glade/glade.h> +#include <gconf/gconf-client.h> + struct usbdev { char *sys; char *tty; @@ -115,4 +118,41 @@ aoview_pres_to_altitude(int16_t pres); int16_t aoview_altitude_to_pres(int16_t alt); +char * +aoview_fullname (char *dir, char *file); + +char * +aoview_basename(char *file); + +GtkTreeViewColumn * +aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width); + +int +aoview_mkdir(char *dir); + +void +aoview_log_init(GladeXML *xml); + +void +aoview_log_set_serial(int serial); + +int +aoview_log_get_serial(void); + +void +aoview_log_printf(char *format, ...); + +void +aoview_table_start(void); + +void +aoview_table_add_row(char *label, char *format, ...); + +void +aoview_table_finish(void); + +void +aoview_table_init(GladeXML *xml); + + #endif /* _AOVIEW_H_ */ diff --git a/aoview/aoview_dev.c b/aoview/aoview_dev.c index 5bb3cc9f..a326ad73 100644 --- a/aoview/aoview_dev.c +++ b/aoview/aoview_dev.c @@ -20,29 +20,9 @@ #include <dirent.h> static char * -fullname (char *dir, char *file) -{ - char *new; - int dlen = strlen (dir); - int flen = strlen (file); - int slen = 0; - - if (dir[dlen-1] != '/') - slen = 1; - new = malloc (dlen + slen + flen + 1); - if (!new) - return 0; - strcpy(new, dir); - if (slen) - strcat (new, "/"); - strcat(new, file); - return new; -} - -static char * load_string(char *dir, char *file) { - char *full = fullname(dir, file); + char *full = aoview_fullname(dir, file); char line[4096]; char *r; FILE *f; @@ -79,17 +59,6 @@ load_hex(char *dir, char *file) return i; } -static char * -basename(char *file) -{ - char *b; - - b = strrchr(file, '/'); - if (!b) - return file; - return b + 1; -} - static int dir_filter_tty(const struct dirent *d) { @@ -110,20 +79,20 @@ usb_tty(char *sys) int ntty; char *tty; - base = basename(sys); + base = aoview_basename(sys); num_configs = load_hex(sys, "bNumConfigurations"); num_interfaces = load_hex(sys, "bNumInterfaces"); for (config = 1; config <= num_configs; config++) { for (interface = 0; interface < num_interfaces; interface++) { sprintf(endpoint_base, "%s:%d.%d", base, config, interface); - endpoint_full = fullname(sys, endpoint_base); + endpoint_full = aoview_fullname(sys, endpoint_base); ntty = scandir(endpoint_full, &namelist, dir_filter_tty, alphasort); free(endpoint_full); if (ntty) { - tty = fullname("/dev", namelist[0]->d_name + 4); + tty = aoview_fullname("/dev", namelist[0]->d_name + 4); free(namelist); return tty; } @@ -196,7 +165,7 @@ aoview_usb_scan(struct usbdev ***devs_ret) if (!n) return 0; for (e = 0; e < n; e++) { - dir = fullname(USB_DEVICES, ents[e]->d_name); + dir = aoview_fullname(USB_DEVICES, ents[e]->d_name); dev = usb_scan_device(dir); free(dir); if (dev->idVendor == 0xfffe && dev->tty) { diff --git a/aoview/aoview_dev_dialog.c b/aoview/aoview_dev_dialog.c index f1165e12..00947404 100644 --- a/aoview/aoview_dev_dialog.c +++ b/aoview/aoview_dev_dialog.c @@ -17,26 +17,6 @@ #include "aoview.h" -static GtkTreeViewColumn * -add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width) -{ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - renderer = gtk_cell_renderer_text_new (); - g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); - g_object_set(renderer, "width-chars", width, NULL); - column = gtk_tree_view_column_new_with_attributes (title, renderer, - "text", model_column, - NULL); - gtk_tree_view_column_set_resizable (column, FALSE); - gtk_tree_view_append_column (view, column); - - return column; -} - - - static void aoview_dev_dialog_map(GtkWidget *widget, gpointer data) { @@ -118,9 +98,9 @@ aoview_dev_dialog_init(GladeXML *xml) dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list")); assert(dev_list); - add_plain_text_column(dev_list, _("Product"), 0, 16); - add_plain_text_column(dev_list, _("Serial"), 1, 8); - add_plain_text_column(dev_list, _("Device"), 2, 13); + aoview_add_plain_text_column(dev_list, _("Product"), 0, 16); + aoview_add_plain_text_column(dev_list, _("Serial"), 1, 8); + aoview_add_plain_text_column(dev_list, _("Device"), 2, 13); dev_selection = gtk_tree_view_get_selection(dev_list); gtk_tree_selection_set_mode(dev_selection, GTK_SELECTION_SINGLE); diff --git a/aoview/aoview_log.c b/aoview/aoview_log.c new file mode 100644 index 00000000..623c5aa6 --- /dev/null +++ b/aoview/aoview_log.c @@ -0,0 +1,192 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "aoview.h" + +#define LOG_DIR_PATH "/apps/aoview/log_dir" +#define DEFAULT_LOG "AltOS" + +static char *aoview_log_dir; +static FILE *aoview_log_file; +static int aoview_log_serial; +static int aoview_log_sequence; +static GtkMessageDialog *log_fail_dialog; +static int aoview_log_failed; + +static void +aoview_log_save_conf(void) +{ + GConfClient *gconf_client; + + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + gconf_client_set_string(gconf_client, + LOG_DIR_PATH, + aoview_log_dir, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + } +} + +static void +aoview_log_configure(GtkWidget *widget, gpointer data) +{ + GtkFileChooser *chooser = data; + aoview_log_dir = gtk_file_chooser_get_filename(chooser); + aoview_log_save_conf(); + gtk_widget_hide(GTK_WIDGET(chooser)); +} + +static void +aoview_log_new(void) +{ + if (aoview_log_file) { + fclose(aoview_log_file); + aoview_log_file = NULL; + } + aoview_log_failed = 0; +} + +static void +aoview_log_new_item(GtkWidget *widget, gpointer data) +{ + aoview_log_new(); +} + +void +aoview_log_set_serial(int serial) +{ + aoview_log_serial = serial; +} + +int +aoview_log_get_serial(void) +{ + return aoview_log_serial; +} + +static void +aoview_log_open_failed(char *name) +{ + char *utf8_file; + utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL); + if (!utf8_file) + utf8_file = name; + gtk_message_dialog_format_secondary_text(log_fail_dialog, + "\"%s\"", utf8_file); + if (utf8_file != name) + g_free(utf8_file); + gtk_widget_show(GTK_WIDGET(log_fail_dialog)); + aoview_log_failed = 1; +} + +static void +aoview_log_start(void) +{ + if (!aoview_log_file) { + char base[50]; + struct tm tm; + time_t now; + char *full; + int r; + + now = time(NULL); + (void) localtime_r(&now, &tm); + aoview_mkdir(aoview_log_dir); + for (;;) { + sprintf(base, "%04d-%02d-%02d-serial-%03d-flight-%03d.log", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + aoview_log_serial, + aoview_log_sequence); + full = aoview_fullname(aoview_log_dir, base); + r = access(full, F_OK); + if (r < 0) { + aoview_log_file = fopen(full, "w"); + if (!aoview_log_file) + aoview_log_open_failed(full); + else + setlinebuf(aoview_log_file); + free(full); + break; + } + free (full); + aoview_log_sequence++; + } + } +} + +void +aoview_log_printf(char *format, ...) +{ + va_list ap; + + if (aoview_log_failed) + return; + aoview_log_start(); + va_start(ap, format); + vfprintf(aoview_log_file, format, ap); + va_end(ap); +} + +void +aoview_log_init(GladeXML *xml) +{ + GConfClient *gconf_client; + char *log_dir = NULL; + GtkFileChooser *log_chooser_dialog; + GtkWidget *log_configure_ok; + GtkWidget *log_new; + + g_type_init(); + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + log_dir = gconf_client_get_string(gconf_client, + LOG_DIR_PATH, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + } + if (!log_dir) { + aoview_log_dir = aoview_fullname(getenv("HOME"), DEFAULT_LOG); + aoview_log_save_conf(); + } else { + aoview_log_dir = strdup(log_dir); + } + + log_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "log_chooser_dialog")); + assert(log_chooser_dialog); + gtk_file_chooser_set_filename(log_chooser_dialog, aoview_log_dir); + + log_configure_ok = glade_xml_get_widget(xml, "log_configure_ok"); + assert(log_configure_ok); + + g_signal_connect(G_OBJECT(log_configure_ok), "clicked", + G_CALLBACK(aoview_log_configure), + log_chooser_dialog); + + log_new = glade_xml_get_widget(xml, "ao_log_new"); + assert(log_new); + g_signal_connect(G_OBJECT(log_new), "activate", + G_CALLBACK(aoview_log_new_item), + NULL); + + log_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "log_fail_dialog")); + assert(log_fail_dialog); +} diff --git a/aoview/aoview_main.c b/aoview/aoview_main.c index 7906e8ac..9e32e639 100644 --- a/aoview/aoview_main.c +++ b/aoview/aoview_main.c @@ -69,6 +69,10 @@ int main(int argc, char **argv) aoview_state_init(xml); + aoview_log_init(xml); + + aoview_table_init(xml); + gtk_main(); return 0; diff --git a/aoview/aoview_monitor.c b/aoview/aoview_monitor.c index 1c9b7189..ba2e9df7 100644 --- a/aoview/aoview_monitor.c +++ b/aoview/aoview_monitor.c @@ -72,7 +72,8 @@ aoview_monitor_parse(char *line) int nword; struct aostate state; - printf ("%s\n", line); + if (aoview_log_get_serial()) + aoview_log_printf ("%s\n", line); for (nword = 0; nword < 64; nword++) { words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; @@ -85,6 +86,9 @@ aoview_monitor_parse(char *line) return; aoview_parse_string(state.callsign, sizeof (state.callsign), words[1]); aoview_parse_int(&state.serial, words[3]); + if (!aoview_log_get_serial()) + aoview_log_set_serial(state.serial); + aoview_parse_int(&state.rssi, words[5]); aoview_parse_string(state.state, sizeof (state.state), words[9]); aoview_parse_int(&state.tick, words[10]); @@ -94,12 +98,15 @@ aoview_monitor_parse(char *line) aoview_parse_int(&state.batt, words[18]); aoview_parse_int(&state.drogue, words[20]); aoview_parse_int(&state.main, words[22]); + aoview_parse_int(&state.nsat, words[24]); if (strcmp (words[26], "unlocked") != 0 && nword >= 29) { + state.locked = 1; sscanf(words[26], "%d:%d:%d", &state.gps_time.hour, &state.gps_time.minute, &state.gps_time.second); aoview_parse_pos(&state.lat, words[27]); aoview_parse_pos(&state.lon, words[28]); sscanf(words[29], "%dm", &state.alt); } else { + state.locked = 0; state.gps_time.hour = state.gps_time.minute = state.gps_time.second = 0; state.lat = state.lon = 0; state.alt = 0; diff --git a/aoview/aoview_state.c b/aoview/aoview_state.c index efd49042..046ccc92 100644 --- a/aoview/aoview_state.c +++ b/aoview/aoview_state.c @@ -66,6 +66,9 @@ aoview_state_notify(struct aostate *state) int ticks; double dist; double bearing; + double temp; + double battery; + double drogue_sense, main_sense; if (!strcmp(state->state, "pad")) { if (npad < NUM_PAD_SAMPLES) { @@ -90,19 +93,39 @@ aoview_state_notify(struct aostate *state) velocity_change = (accel + prev_accel) / 2.0; ticks = state->tick - prev_tick; velocity -= velocity_change * (ticks / 100.0); + temp = ((state->temp / 32767.0 * 3.3) - 0.5) / 0.01; + battery = (state->batt / 32767.0 * 5.0); + drogue_sense = (state->drogue / 32767.0 * 15.0); + main_sense = (state->main / 32767.0 * 15.0); prev_accel = accel; prev_tick = state->tick; - printf ("Pad altitude: %dm\n", aoview_pres_to_altitude(pad_pres)); - printf ("AGL: %dm\n", altitude); - printf ("Acceleration: %gm/s²\n", accel); - printf ("Velocity: %gm/s\n", velocity); - printf ("Lat: %g\n", state->lat); - printf ("Lon: %g\n", state->lon); - printf ("GPS alt: %d\n", state->alt); - aoview_great_circle(pad_lat, pad_lon, state->lat, state->lon, - &dist, &bearing); - printf ("Course: %gkm %g°\n", dist, bearing); + aoview_table_start(); + aoview_table_add_row("RSSI", "%ddB", state->rssi); + aoview_table_add_row("Height", "%dm", altitude); + aoview_table_add_row("Acceleration", "%gm/s²", accel); + aoview_table_add_row("Velocity", "%gm/s", velocity); + aoview_table_add_row("Temperature", "%g°C", temp); + aoview_table_add_row("Battery", "%gV", battery); + aoview_table_add_row("Drogue", "%gV", drogue_sense); + aoview_table_add_row("Main", "%gV", main_sense); + aoview_table_add_row("Pad altitude", "%dm", aoview_pres_to_altitude(pad_pres)); + aoview_table_add_row("Satellites", "%d", state->nsat); + if (state->locked) { + aoview_table_add_row("Lat", "%g", state->lat); + aoview_table_add_row("Lon", "%g", state->lon); + aoview_table_add_row("GPS alt", "%d", state->alt); + aoview_table_add_row("GPS time", "%02d:%02d:%02d", + state->gps_time.hour, + state->gps_time.minute, + state->gps_time.second); + aoview_great_circle(pad_lat, pad_lon, state->lat, state->lon, + &dist, &bearing); + aoview_table_add_row("Course", "%gkm %g°", dist, bearing); + } else { + aoview_table_add_row("GPS", "unlocked"); + } + aoview_table_finish(); } void diff --git a/aoview/aoview_table.c b/aoview/aoview_table.c new file mode 100644 index 00000000..90deeb91 --- /dev/null +++ b/aoview/aoview_table.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "aoview.h" + +static GtkTreeView *dataview; +static GtkListStore *datalist; + +void +aoview_table_start(void) +{ + datalist = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); +} + +void +aoview_table_add_row(char *label, char *format, ...) +{ + char buf[1024]; + va_list ap; + GtkTreeIter iter; + + va_start(ap, format); + vsnprintf(buf, sizeof (buf), format, ap); + va_end(ap); + gtk_list_store_append(datalist, &iter); + gtk_list_store_set(datalist, &iter, + 0, label, + 1, buf, + -1); +} + +void +aoview_table_finish(void) +{ + gtk_tree_view_set_model(dataview, GTK_TREE_MODEL(datalist)); + g_object_unref(G_OBJECT(datalist)); + gtk_tree_view_columns_autosize(dataview); +} + +void +aoview_table_init(GladeXML *xml) +{ + dataview = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dataview")); + assert(dataview); + + aoview_add_plain_text_column(dataview, "Field", 0, 16); + aoview_add_plain_text_column(dataview, "Value", 1, 32); +} diff --git a/aoview/aoview_util.c b/aoview/aoview_util.c new file mode 100644 index 00000000..6ea62ac9 --- /dev/null +++ b/aoview/aoview_util.c @@ -0,0 +1,91 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "aoview.h" + +char * +aoview_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +char * +aoview_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +int +aoview_mkdir(char *dir) +{ + char *slash; + char *d; + char *part; + + d = dir; + for (;;) { + slash = strchr (d, '/'); + if (!slash) + slash = d + strlen(d); + if (!*slash) + break; + part = strndup(dir, slash - dir); + if (!access(part, F_OK)) + if (mkdir(part, 0777) < 0) + return -errno; + free(part); + d = slash + 1; + } + return 0; +} + +GtkTreeViewColumn * +aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); + g_object_set(renderer, "width-chars", width, NULL); + column = gtk_tree_view_column_new_with_attributes (title, renderer, + "text", model_column, + NULL); + gtk_tree_view_column_set_resizable (column, FALSE); + gtk_tree_view_append_column (view, column); + + return column; +} |