diff options
| -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; +} | 
