Move usb scanning code to ao-tools library
authorKeith Packard <keithp@keithp.com>
Fri, 4 Sep 2009 20:00:02 +0000 (13:00 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 4 Sep 2009 20:00:02 +0000 (13:00 -0700)
This will allow the scanning code to be used by the command line tools
as well as the ao-view GUI.

Now that ao-view depends on the ao-tools library, it has been moved to
the ao-tools directory as well.

Signed-off-by: Keith Packard <keithp@keithp.com>
51 files changed:
INSTALL
Makefile.am
ao-tools/Makefile.am
ao-tools/ao-view/.gitignore [new file with mode: 0644]
ao-tools/ao-view/Makefile.am [new file with mode: 0644]
ao-tools/ao-view/ao-view.1 [new file with mode: 0644]
ao-tools/ao-view/aoview.glade [new file with mode: 0644]
ao-tools/ao-view/aoview.h [new file with mode: 0644]
ao-tools/ao-view/aoview_convert.c [new file with mode: 0644]
ao-tools/ao-view/aoview_dev_dialog.c [new file with mode: 0644]
ao-tools/ao-view/aoview_eeprom.c [new file with mode: 0644]
ao-tools/ao-view/aoview_file.c [new file with mode: 0644]
ao-tools/ao-view/aoview_flite.c [new file with mode: 0644]
ao-tools/ao-view/aoview_label.c [new file with mode: 0644]
ao-tools/ao-view/aoview_log.c [new file with mode: 0644]
ao-tools/ao-view/aoview_main.c [new file with mode: 0644]
ao-tools/ao-view/aoview_monitor.c [new file with mode: 0644]
ao-tools/ao-view/aoview_replay.c [new file with mode: 0644]
ao-tools/ao-view/aoview_serial.c [new file with mode: 0644]
ao-tools/ao-view/aoview_state.c [new file with mode: 0644]
ao-tools/ao-view/aoview_table.c [new file with mode: 0644]
ao-tools/ao-view/aoview_util.c [new file with mode: 0644]
ao-tools/ao-view/aoview_voice.c [new file with mode: 0644]
ao-tools/ao-view/design [new file with mode: 0644]
ao-tools/lib/Makefile.am
ao-tools/lib/cc-usbdev.c [new file with mode: 0644]
ao-tools/lib/cc-util.c [new file with mode: 0644]
ao-tools/lib/cc.h [new file with mode: 0644]
ao-view/.gitignore [deleted file]
ao-view/Makefile.am [deleted file]
ao-view/ao-view.1 [deleted file]
ao-view/aoview.glade [deleted file]
ao-view/aoview.h [deleted file]
ao-view/aoview_convert.c [deleted file]
ao-view/aoview_dev.c [deleted file]
ao-view/aoview_dev_dialog.c [deleted file]
ao-view/aoview_eeprom.c [deleted file]
ao-view/aoview_file.c [deleted file]
ao-view/aoview_flite.c [deleted file]
ao-view/aoview_label.c [deleted file]
ao-view/aoview_log.c [deleted file]
ao-view/aoview_main.c [deleted file]
ao-view/aoview_monitor.c [deleted file]
ao-view/aoview_replay.c [deleted file]
ao-view/aoview_serial.c [deleted file]
ao-view/aoview_state.c [deleted file]
ao-view/aoview_table.c [deleted file]
ao-view/aoview_util.c [deleted file]
ao-view/aoview_voice.c [deleted file]
ao-view/design [deleted file]
configure.ac

diff --git a/INSTALL b/INSTALL
index 8b82ade08e87bbfb02fbf4c3b45b181ab6dda8cb..2550dab75261145b56f3d223673e00bef2aa78df 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -2,7 +2,7 @@ Installation Instructions
 *************************
 
 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007, 2008 Free Software Foundation, Inc.
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
@@ -159,7 +159,7 @@ Particular systems
 CC is not installed, it is recommended to use the following options in
 order to use an ANSI C compiler:
 
-     ./configure CC="cc -Ae"
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
 
 and if that doesn't work, install pre-built binaries of GCC for HP-UX.
 
@@ -174,6 +174,16 @@ and if that doesn't work, try
 
      ./configure CC="cc -nodtk"
 
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
 Specifying the System Type
 ==========================
 
@@ -189,7 +199,8 @@ type, such as `sun4', or a canonical name which has the form:
 
 where SYSTEM can have one of these forms:
 
-     OS KERNEL-OS
+     OS
+     KERNEL-OS
 
    See the file `config.sub' for the possible values of each field.  If
 `config.sub' isn't included in this package, then this package doesn't
index 96b9dea91d87f110abcc60149ada5d79e1b529f6..39e7c2446130cce0c7ba0874c3c00fd8c49b6951 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS=src ao-view ao-tools ao-utils
+SUBDIRS=src ao-tools ao-utils
 
 EXTRA_DIST = ChangeLog
 
index 98b88f38b4382dfc8d5374874d5e84f966c99757..02b4785e52c0215027e4c8645e190a12d917e479 100644 (file)
@@ -1 +1 @@
-SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-load
+SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-load ao-view
diff --git a/ao-tools/ao-view/.gitignore b/ao-tools/ao-view/.gitignore
new file mode 100644 (file)
index 0000000..24fbc59
--- /dev/null
@@ -0,0 +1,4 @@
+*.o
+aoview
+aoview_glade.h
+aoview_flite
diff --git a/ao-tools/ao-view/Makefile.am b/ao-tools/ao-view/Makefile.am
new file mode 100644 (file)
index 0000000..7b274a4
--- /dev/null
@@ -0,0 +1,37 @@
+VERSION=$(shell git describe)
+
+AO_VIEW_CFLAGS=-I$(top_srcdir)/ao-tools/lib
+AO_VIEW_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+AM_CFLAGS=$(AO_VIEW_CFLAGS) $(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
+
+bin_PROGRAMS=ao-view
+
+ao_view_DEPENDENCIES=$(AO_VIEW_LIBS)
+ao_view_LDADD=$(GNOME_LIBS) $(FLITE_LIBS) $(ALSA_LIBS) $(AO_VIEW_LIBS) $(LIBUSB_LIBS)
+
+ao_view_SOURCES = \
+       aoview_main.c \
+       aoview_dev_dialog.c \
+       aoview_serial.c \
+       aoview_monitor.c \
+       aoview_state.c \
+       aoview_convert.c \
+       aoview_log.c \
+       aoview_table.c \
+       aoview_util.c \
+       aoview_file.c \
+       aoview_eeprom.c \
+       aoview_voice.c \
+       aoview_replay.c \
+       aoview_label.c \
+       aoview_flite.c \
+       aoview.h
+
+BUILT_SOURCES = aoview_glade.h
+
+CLEANFILES = aoview_glade.h
+
+man_MANS=ao-view.1
+
+aoview_glade.h: aoview.glade
+       sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
diff --git a/ao-tools/ao-view/ao-view.1 b/ao-tools/ao-view/ao-view.1
new file mode 100644 (file)
index 0000000..99834c4
--- /dev/null
@@ -0,0 +1,50 @@
+.\"
+.\" 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; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" 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.
+.\"
+.\"
+.TH AO-VIEW 1 "ao-view" ""
+.SH NAME
+ao-view \- Rocket flight monitor
+.SH SYNOPSIS
+.B "ao-view"
+[\--tty \fItty-device\fP]
+.SH DESCRIPTION
+.I ao-view
+connects to a TeleDongle or TeleMetrum device through a USB serial device.
+It provides a user interface to monitor, record and review rocket flight data.
+.SH OPTIONS
+The usual Gtk+ command line options can be used, along with
+.IP "\--tty"
+This selects a target device to connect at startup time to.
+The target device may also be selected through the user interface.
+.SH USAGE
+When connected to a TeleDongle device, ao-view turns on the radio
+receiver and listens for telemetry packets. It displays the received
+telemetry data, and reports flight status via voice synthesis. All
+received telemetry information is recorded to a file.
+.P
+When connected to a TeleMetrum device, ao-view downloads the eeprom
+data and stores it in a file.
+.SH FILES
+All data log files are recorded into a user-specified directory
+(default ~/AltOS). Files are named using the current date, the serial
+number of the reporting device, the flight number recorded in the data
+and either '.telem' for telemetry data or '.eeprom' for eeprom data.
+.SH "SEE ALSO"
+ao-load(1), ao-eeprom(1)
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-view/aoview.glade b/ao-tools/ao-view/aoview.glade
new file mode 100644 (file)
index 0000000..9a74611
--- /dev/null
@@ -0,0 +1,744 @@
+<?xml version="1.0"?>
+<glade-interface>
+  <!-- interface-requires gtk+ 2.16 -->
+  <!-- interface-naming-policy project-wide -->
+  <widget class="GtkWindow" id="aoview">
+    <property name="width_request">900</property>
+    <property name="height_request">700</property>
+    <property name="visible">True</property>
+    <property name="title" translatable="yes">AltOS View</property>
+    <child>
+      <widget class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <widget class="GtkMenuBar" id="menubar1">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkMenuItem" id="menuitem1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_File</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="menu1">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem1">
+                        <property name="label">gtk-new</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem2">
+                        <property name="label">gtk-open</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem3">
+                        <property name="label">gtk-save</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem4">
+                        <property name="label">gtk-save-as</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem5">
+                        <property name="label">gtk-quit</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="gtk_main_quit"/>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="menuitem2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Edit</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="menu2">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem6">
+                        <property name="label">gtk-cut</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem7">
+                        <property name="label">gtk-copy</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem8">
+                        <property name="label">gtk-paste</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem9">
+                        <property name="label">gtk-delete</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="menuitem3">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Device</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="menu4">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="ao_connect">
+                        <property name="label" translatable="yes">_Connect to device</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">False</property>
+                        <signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
+                        <signal name="activate" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image1">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-connect</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="ao_disconnect">
+                        <property name="label" translatable="yes">_Disconnect</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="image2">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-disconnect</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="seperator">
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="ao_savelog">
+                        <property name="label" translatable="yes">_Save EEPROM data</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">False</property>
+                        <signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
+                        <signal name="activate" handler="gtk_widget_show" object="device_connect_dialog"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image5">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-save</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="ao_replay">
+                        <property name="label" translatable="yes">_Replay</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">False</property>
+                        <signal name="activate_item" handler="gtk_widget_show" object="ao_replay_dialog" after="yes"/>
+                        <signal name="activate" handler="gtk_widget_show" object="ao_replay_dialog"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image6">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-media-play</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </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="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="file_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="file_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="menuitem6">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Voice</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="menu6">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkCheckMenuItem" id="voice_enable">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Enable _Voice</property>
+                        <property name="use_underline">True</property>
+                        <property name="active">True</property>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="menuitem4">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Help</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="menu3">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="imagemenuitem10">
+                        <property name="label">gtk-about</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="gtk_widget_show" object="about_dialog" after="yes"/>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="n_rows">2</property>
+            <property name="n_columns">4</property>
+            <property name="row_spacing">3</property>
+            <property name="homogeneous">True</property>
+            <child>
+              <widget class="GtkLabel" id="height_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Height (m)</property>
+                <property name="justify">center</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="state_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">State</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="rssi_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">RSSI (dBm)</property>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="height_value">
+                <property name="visible">True</property>
+                <property name="ypad">2</property>
+                <property name="label" translatable="yes">0</property>
+                <property name="selectable">True</property>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="state_value">
+                <property name="visible">True</property>
+                <property name="ypad">2</property>
+                <property name="label" translatable="yes">pad</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="rssi_value">
+                <property name="visible">True</property>
+                <property name="ypad">2</property>
+                <property name="label" translatable="yes">-50</property>
+                <property name="selectable">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="speed_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Speed (m/s)</property>
+              </widget>
+              <packing>
+                <property name="left_attach">3</property>
+                <property name="right_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="speed_value">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">0</property>
+                <property name="selectable">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">3</property>
+                <property name="right_attach">4</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkTreeView" id="dataview_0">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="show_expanders">False</property>
+                <property name="enable_grid_lines">both</property>
+              </widget>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkTreeView" id="dataview_1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="show_expanders">False</property>
+                <property name="enable_grid_lines">both</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkTreeView" id="dataview_2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="show_expanders">False</property>
+                <property name="enable_grid_lines">both</property>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="device_connect_dialog">
+    <property name="border_width">5</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkTreeView" id="dev_list">
+            <property name="width_request">300</property>
+            <property name="height_request">100</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="headers_clickable">False</property>
+            <property name="rules_hint">True</property>
+            <property name="search_column">0</property>
+            <property name="show_expanders">False</property>
+            <property name="level_indentation">1</property>
+            <property name="enable_grid_lines">both</property>
+            <property name="enable_tree_lines">True</property>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="cancel_button">
+                <property name="label">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>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="connect_button">
+                <property name="label">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="file_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="file_configure_cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gtk_widget_hide" object="file_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="file_configure_ok">
+                <property name="label">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>
+                <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="GtkMessageDialog" id="file_fail_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Failed to create log</property>
+    <property name="type_hint">normal</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</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>
+  <widget class="GtkMessageDialog" id="dev_open_fail_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Failed to open device</property>
+    <property name="type_hint">normal</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</property>
+    <property name="message_type">error</property>
+    <property name="buttons">close</property>
+    <property name="text">Cannot open device</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox6">
+        <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_area6">
+            <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>
+  <widget class="GtkAboutDialog" id="about_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">About AoView</property>
+    <property name="resizable">False</property>
+    <property name="type_hint">normal</property>
+    <property name="transient_for">aoview</property>
+    <property name="has_separator">False</property>
+    <property name="program_name">AoView</property>
+    <property name="copyright" translatable="yes">Copyright &#xA9; 2009 Keith Packard</property>
+    <property name="comments" translatable="yes">AltOS data capture and display.</property>
+    <property name="website">http://altusmetrum.org</property>
+    <property name="license" translatable="yes">AoView 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.
+
+AoView 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 AoView; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</property>
+    <property name="authors">Keith Packard &lt;keithp@keithp.com&gt;</property>
+    <property name="wrap_license">True</property>
+    <signal name="close" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
+    <signal name="response" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox7">
+        <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_area7">
+            <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>
+  <widget class="GtkMessageDialog" id="ao_save_done">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">EEPROM save complete</property>
+    <property name="type_hint">normal</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</property>
+    <property name="buttons">close</property>
+    <property name="text">Saving EEPROM data as</property>
+    <property name="secondary_text">&lt;filename&gt;</property>
+    <signal name="close" handler="gtk_widget_hide" object="ao_save_done"/>
+    <signal name="response" handler="gtk_widget_hide" object="ao_save_done"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox11">
+        <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_area11">
+            <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>
+  <widget class="GtkFileChooserDialog" id="ao_replay_dialog">
+    <property name="border_width">5</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox10">
+        <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_area10">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="ao_replay_cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gtk_widget_hide" object="ao_replay_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="ao_replay_ok">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">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>
+</glade-interface>
diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h
new file mode 100644 (file)
index 0000000..6a4753a
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ */
+
+#ifndef _AOVIEW_H_
+#define _AOVIEW_H_
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <math.h>
+
+#include "cc.h"
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf-client.h>
+
+struct aogps_time {
+       int hour;
+       int minute;
+       int second;
+};
+
+struct aogps {
+       int     nsat;
+       int     gps_locked;
+       int     gps_connected;
+       struct aogps_time gps_time;
+       double  lat;            /* degrees (+N -S) */
+       double  lon;            /* degrees (+E -W) */
+       int     alt;            /* m */
+
+       int     gps_extended;   /* has extra data */
+       double  ground_speed;   /* m/s */
+       int     course;         /* degrees */
+       double  climb_rate;     /* m/s */
+       double  hdop;           /* unitless? */
+       int     h_error;        /* m */
+       int     v_error;        /* m */
+};
+
+#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
+#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
+#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
+#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
+#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
+#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
+#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
+#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
+
+struct aogps_sat {
+       int     svid;
+       int     state;
+       int     c_n0;
+};
+
+struct aogps_tracking {
+       int                     channels;
+       struct aogps_sat        sats[12];
+};
+
+struct aodata {
+       char    callsign[16];
+       int     serial;
+       int     rssi;
+       char    state[16];
+       int     tick;
+       int     accel;
+       int     pres;
+       int     temp;
+       int     batt;
+       int     drogue;
+       int     main;
+       int     flight_accel;
+       int     ground_accel;
+       int     flight_vel;
+       int     flight_pres;
+       int     ground_pres;
+       struct aogps    gps;
+       struct aogps_tracking   gps_tracking;
+};
+
+struct aostate {
+       struct aodata   data;
+
+       /* derived data */
+
+       struct aodata   prev_data;
+
+       double          report_time;
+
+       gboolean        ascent; /* going up? */
+
+       int     ground_altitude;
+       int     height;
+       double  speed;
+       double  acceleration;
+       double  battery;
+       double  temperature;
+       double  main_sense;
+       double  drogue_sense;
+       double  baro_speed;
+
+       int     max_height;
+       double  max_acceleration;
+       double  max_speed;
+
+       struct aogps    gps;
+       struct aogps_tracking   gps_tracking;
+
+       int     gps_valid;
+       double  pad_lat;
+       double  pad_lon;
+       double  pad_alt;
+       double  pad_lat_total;
+       double  pad_lon_total;
+       double  pad_alt_total;
+       int     npad;
+       int     prev_npad;
+
+       double  distance;
+       double  bearing;
+       int     gps_height;
+
+       int     speak_tick;
+       int     speak_altitude;
+};
+
+extern struct aostate aostate;
+
+/* GPS is 'stable' when we've seen at least this many samples */
+#define MIN_PAD_SAMPLES        10
+
+void
+aoview_monitor_disconnect(void);
+
+gboolean
+aoview_monitor_connect(char *tty);
+
+gboolean
+aoview_monitor_parse(const char *line);
+
+void
+aoview_monitor_reset(void);
+
+struct aoview_serial *
+aoview_serial_open(const char *tty);
+
+void
+aoview_serial_close(struct aoview_serial *serial);
+
+typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents);
+
+void
+aoview_serial_set_callback(struct aoview_serial *serial,
+                          aoview_serial_callback func);
+
+void
+aoview_serial_printf(struct aoview_serial *serial, char *format, ...);
+
+int
+aoview_serial_read(struct aoview_serial *serial, char *buf, int len);
+
+int
+aoview_serial_getc(struct aoview_serial *serial);
+
+void
+aoview_dev_dialog_init(GladeXML *xml);
+
+void
+aoview_state_notify(struct aodata *data);
+
+void
+aoview_state_new(void);
+
+void
+aoview_state_init(GladeXML *xml);
+
+int16_t
+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_log_new(void);
+
+void
+aoview_table_start(void);
+
+void
+aoview_table_add_row(int column, char *label, char *format, ...);
+
+void
+aoview_table_finish(void);
+
+void
+aoview_table_init(GladeXML *xml);
+
+void
+aoview_table_clear(void);
+
+struct aoview_file;
+
+extern char *aoview_file_dir;
+
+void
+aoview_file_finish(struct aoview_file *file);
+
+gboolean
+aoview_file_start(struct aoview_file *file);
+
+const char *
+aoview_file_name(struct aoview_file *file);
+
+void
+aoview_file_set_serial(struct aoview_file *file, int serial);
+
+int
+aoview_file_get_serial(struct aoview_file *file);
+
+void
+aoview_file_printf(struct aoview_file *file, char *format, ...);
+
+void
+aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap);
+
+struct aoview_file *
+aoview_file_new(char *ext);
+
+void
+aoview_file_destroy(struct aoview_file *file);
+
+void
+aoview_file_init(GladeXML *xml);
+
+/* aoview_eeprom.c */
+
+gboolean
+aoview_eeprom_save(const char *device);
+
+void
+aoview_eeprom_init(GladeXML *xml);
+
+/* aoview_voice.c */
+void aoview_voice_open(void);
+
+void aoview_voice_close(void);
+
+void aoview_voice_speak(char *format, ...);
+
+/* aoview_label.c */
+
+void aoview_label_init(GladeXML *xml);
+
+void
+aoview_label_show(struct aostate *state);
+
+/* aoview_flite.c */
+
+FILE *
+aoview_flite_start(void);
+
+void
+aoview_flite_stop(void);
+
+/* aoview_main.c */
+
+extern char *aoview_tty;
+
+#endif /* _AOVIEW_H_ */
diff --git a/ao-tools/ao-view/aoview_convert.c b/ao-tools/ao-view/aoview_convert.c
new file mode 100644 (file)
index 0000000..0241664
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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 int16_t altitude_table[2048] = {
+#include "altitude.h"
+};
+
+int16_t
+aoview_pres_to_altitude(int16_t pres)
+{
+       pres = pres >> 4;
+       if (pres < 0) pres = 0;
+       if (pres > 2047) pres = 2047;
+       return altitude_table[pres];
+}
+
+int16_t
+aoview_altitude_to_pres(int16_t alt)
+{
+       int16_t pres;
+
+       for (pres = 0; pres < 2047; pres++)
+               if (altitude_table[pres] <= alt)
+                       break;
+       return pres << 4;
+}
diff --git a/ao-tools/ao-view/aoview_dev_dialog.c b/ao-tools/ao-view/aoview_dev_dialog.c
new file mode 100644 (file)
index 0000000..87396c1
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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 void
+aoview_dev_dialog_map(GtkWidget *widget, gpointer data)
+{
+       GtkTreeView     *dev_list = data;
+       GtkListStore    *list_store;
+       GtkTreeIter     iter;
+       int             ndev, n;
+       struct cc_usbdevs       *devs;
+       struct cc_usbdev        *dev;
+
+       list_store = gtk_list_store_new(3,
+                                       G_TYPE_STRING,
+                                       G_TYPE_STRING,
+                                       G_TYPE_STRING);
+
+       devs = cc_usbdevs_scan();
+       if (devs) {
+               for (n = 0; n < devs->ndev; n++) {
+                       dev = devs->dev[n];
+                       gtk_list_store_append(list_store, &iter);
+                       gtk_list_store_set(list_store, &iter,
+                                          0, dev->product,
+                                          1, dev->serial,
+                                          2, dev->tty,
+                                          -1);
+               }
+       }
+       gtk_tree_view_set_model (dev_list, GTK_TREE_MODEL(list_store));
+       g_object_unref(G_OBJECT(list_store));
+       gtk_tree_view_columns_autosize(dev_list);
+       cc_usbdevs_free(devs);
+}
+
+static GtkMessageDialog *dev_open_fail_dialog;
+
+static void
+aoview_dev_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(dev_open_fail_dialog,
+                                                "\"%s\"", utf8_file);
+       if (utf8_file != name)
+               g_free(utf8_file);
+       gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog));
+       gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog));
+}
+
+gboolean       dialog_save_log;
+
+static void
+aoview_dev_selected(GtkTreeModel *model,
+                   GtkTreePath *path,
+                   GtkTreeIter *iter,
+                   gpointer data)
+{
+       gchar *string;
+       gtk_tree_model_get(model, iter,
+                          2, &string,
+                          -1);
+       if (dialog_save_log) {
+               dialog_save_log = FALSE;
+               if (!aoview_eeprom_save(string))
+                       aoview_dev_open_failed(string);
+       } else {
+               if (!aoview_monitor_connect(string))
+                       aoview_dev_open_failed(string);
+       }
+}
+
+static GtkWidget       *dialog;
+
+static void
+aoview_dev_dialog_connect(GtkWidget *widget, gpointer data)
+{
+       GtkTreeView             *dev_list = data;
+       GtkListStore            *list_store;
+       GtkTreeSelection        *tree_selection;
+
+       list_store = GTK_LIST_STORE(gtk_tree_view_get_model(dev_list));
+       tree_selection = gtk_tree_view_get_selection(dev_list);
+       gtk_tree_selection_selected_foreach(tree_selection,
+                                           aoview_dev_selected,
+                                           data);
+       gtk_widget_hide(dialog);
+}
+
+static void
+aoview_dev_disconnect(GtkWidget *widget)
+{
+       aoview_monitor_disconnect();
+}
+
+static void
+aoview_dev_savelog(GtkWidget *widget, gpointer data)
+{
+       dialog_save_log = TRUE;
+       gtk_widget_show(dialog);
+}
+
+#define _(a) a
+
+void
+aoview_dev_dialog_init(GladeXML *xml)
+{
+       GtkTreeView     *dev_list;
+       GtkWidget       *connect_button;
+       GtkTreeSelection        *dev_selection;
+       GtkWidget       *ao_disconnect;
+       GtkWidget       *ao_savelog;
+
+       dialog = glade_xml_get_widget(xml, "device_connect_dialog");
+       assert(dialog);
+
+       dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list"));
+       assert(dev_list);
+
+       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);
+
+       g_signal_connect(G_OBJECT(dialog), "map",
+                        G_CALLBACK(aoview_dev_dialog_map),
+                        dev_list);
+
+       connect_button = glade_xml_get_widget(xml, "connect_button");
+       assert(connect_button);
+
+       g_signal_connect(G_OBJECT(connect_button), "clicked",
+                        G_CALLBACK(aoview_dev_dialog_connect),
+                        dev_list);
+
+
+       ao_disconnect = glade_xml_get_widget(xml, "ao_disconnect");
+       assert(ao_disconnect);
+
+       g_signal_connect(G_OBJECT(ao_disconnect), "activate",
+                        G_CALLBACK(aoview_dev_disconnect),
+                        ao_disconnect);
+
+       ao_savelog = glade_xml_get_widget(xml, "ao_savelog");
+       assert(ao_savelog);
+
+       g_signal_connect(G_OBJECT(ao_savelog), "activate",
+                        G_CALLBACK(aoview_dev_savelog),
+                        dialog);
+       dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog"));
+       assert(dev_open_fail_dialog);
+}
diff --git a/ao-tools/ao-view/aoview_eeprom.c b/ao-tools/ao-view/aoview_eeprom.c
new file mode 100644 (file)
index 0000000..34e2dee
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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 EEPROM_LEN     1024
+
+static struct aoview_file      *eeprom_file;
+static char                    eeprom_line[EEPROM_LEN + 1];
+static int                     eeprom_pos;
+static GtkMessageDialog                *eeprom_save_done;
+static GtkWidget               *eeprom_save_close;
+static gboolean                        eeprom_save_shown;
+
+static void
+aoview_eeprom_disconnect(struct aoview_serial *serial)
+{
+       aoview_file_finish(eeprom_file);
+}
+
+static void
+aoview_eeprom_done(struct aoview_serial *serial)
+{
+       gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
+                            "EEPROM data saved");
+       gtk_message_dialog_set_markup(eeprom_save_done,
+                                     "<b>EEPROM data saved as</b>");
+       if (!eeprom_save_shown)
+               gtk_widget_show(GTK_WIDGET(eeprom_save_done));
+       eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
+       if (eeprom_save_close)
+               gtk_widget_set_sensitive(eeprom_save_close, TRUE);
+       aoview_eeprom_disconnect(serial);
+}
+
+static gboolean
+aoview_eeprom_parse(struct aoview_serial *serial,
+                   char *line)
+{
+       char            cmd;
+       int             tick;
+       int             a;
+       int             b;
+       int             serial_number;
+       const char      *name;
+       char            *utf8_name;
+
+       if (!strcmp(line, "end")) {
+               aoview_eeprom_done(serial);
+               return FALSE;
+       }
+       if (sscanf(line, "serial-number %u", &serial_number) == 1) {
+               aoview_file_set_serial(eeprom_file, serial_number);
+       } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) {
+               aoview_file_printf(eeprom_file, "%s\n", line);
+               if (cmd == 'S' && a == 8) {
+                       aoview_eeprom_done(serial);
+                       return FALSE;
+               }
+
+               if (!eeprom_save_shown)
+               {
+                       name = aoview_file_name(eeprom_file);
+                       if (name) {
+                               utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+                               if (!utf8_name)
+                                       utf8_name = (char *) name;
+                               gtk_widget_set_sensitive(eeprom_save_close, FALSE);
+                               gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
+                                                    "Saving EEPROM data");
+                               gtk_message_dialog_set_markup(eeprom_save_done,
+                                                             "<b>Saving EEPROM data as</b>");
+                               gtk_message_dialog_format_secondary_text(eeprom_save_done, "%s",
+                                                                        utf8_name);
+                               if (utf8_name != name)
+                                       g_free(utf8_name);
+                               gtk_container_check_resize(GTK_CONTAINER(eeprom_save_done));
+                               gtk_widget_show(GTK_WIDGET(eeprom_save_done));
+                               eeprom_save_shown = TRUE;
+                               eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
+                               if (eeprom_save_close)
+                                       gtk_widget_set_sensitive(eeprom_save_close, FALSE);
+                       }
+               }
+       }
+       return TRUE;
+}
+
+static void
+aoview_eeprom_callback(gpointer user_data,
+                      struct aoview_serial *serial,
+                      gint revents)
+{
+       int     c;
+
+       if (revents & (G_IO_HUP|G_IO_ERR)) {
+               aoview_eeprom_disconnect(serial);
+               return;
+       }
+       if (revents & G_IO_IN) {
+               for (;;) {
+                       c = aoview_serial_getc(serial);
+                       if (c == -1)
+                               break;
+                       if (c == '\r')
+                               continue;
+                       if (c == '\n') {
+                               eeprom_line[eeprom_pos] = '\0';
+                               if (eeprom_pos)
+                               if (!aoview_eeprom_parse(serial, eeprom_line))
+                                       break;
+                               eeprom_pos = 0;
+                       } else if (eeprom_pos < EEPROM_LEN)
+                               eeprom_line[eeprom_pos++] = c;
+               }
+       }
+}
+
+gboolean
+aoview_eeprom_save(const char *device)
+{
+       struct aoview_serial    *serial;
+
+       gtk_widget_hide(GTK_WIDGET(eeprom_save_done));
+       eeprom_save_shown = FALSE;
+       serial = aoview_serial_open(device);
+       if (!serial)
+               return FALSE;
+       aoview_serial_set_callback(serial, aoview_eeprom_callback);
+       aoview_serial_printf(serial, "v\nl\n");
+       return TRUE;
+}
+
+void
+aoview_eeprom_init(GladeXML *xml)
+{
+       eeprom_file = aoview_file_new("eeprom");
+       assert(eeprom_file);
+
+       eeprom_save_done = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "ao_save_done"));
+       assert(eeprom_save_done);
+
+}
diff --git a/ao-tools/ao-view/aoview_file.c b/ao-tools/ao-view/aoview_file.c
new file mode 100644 (file)
index 0000000..5288c2f
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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_file_dir;
+
+#define ALTOS_DIR_PATH "/apps/aoview/log_dir"
+#define DEFAULT_DIR    "AltOS"
+
+struct aoview_file {
+       char    *ext;
+       FILE    *file;
+       char    *name;
+       int     failed;
+       int     serial;
+       int     sequence;
+};
+
+static void
+aoview_file_save_conf(void)
+{
+       GConfClient     *gconf_client;
+
+       gconf_client = gconf_client_get_default();
+       if (gconf_client)
+       {
+               gconf_client_set_string(gconf_client,
+                                       ALTOS_DIR_PATH,
+                                       aoview_file_dir,
+                                       NULL);
+               g_object_unref(G_OBJECT(gconf_client));
+       }
+}
+
+static void
+aoview_file_configure(GtkWidget *widget, gpointer data)
+{
+       GtkFileChooser *chooser = data;
+       aoview_file_dir = gtk_file_chooser_get_filename(chooser);
+       aoview_file_save_conf();
+       gtk_widget_hide(GTK_WIDGET(chooser));
+}
+
+void
+aoview_file_finish(struct aoview_file *file)
+{
+       if (file->file) {
+               fclose(file->file);
+               file->file = NULL;
+               free(file->name);
+               file->name = NULL;
+       }
+       file->failed = 0;
+}
+
+const char *
+aoview_file_name(struct aoview_file *file)
+{
+       return file->name;
+}
+
+static GtkMessageDialog *file_fail_dialog;
+
+static void
+aoview_file_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(file_fail_dialog,
+                                                "\"%s\"", utf8_file);
+       if (utf8_file != name)
+               g_free(utf8_file);
+       gtk_widget_show(GTK_WIDGET(file_fail_dialog));
+}
+
+gboolean
+aoview_file_start(struct aoview_file *file)
+{
+       char            base[50];
+       struct tm       tm;
+       time_t          now;
+       char            *full;
+       int             r;
+
+       if (file->file)
+               return TRUE;
+
+       if (file->failed)
+               return FALSE;
+
+       now = time(NULL);
+       (void) localtime_r(&now, &tm);
+       aoview_mkdir(aoview_file_dir);
+       for (;;) {
+               snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
+                       tm.tm_year + 1900,
+                       tm.tm_mon + 1,
+                       tm.tm_mday,
+                       file->serial,
+                       file->sequence,
+                       file->ext);
+               full = aoview_fullname(aoview_file_dir, base);
+               r = access(full, F_OK);
+               if (r < 0) {
+                       file->file = fopen(full, "w");
+                       if (!file->file) {
+                               aoview_file_open_failed(full);
+                               free(full);
+                               file->failed = 1;
+                               return FALSE;
+                       } else {
+                               setlinebuf(file->file);
+                               file->name = full;
+                               return TRUE;
+                       }
+               }
+               free(full);
+               file->sequence++;
+       }
+}
+
+void
+aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap)
+{
+       if (!aoview_file_start(file))
+               return;
+       vfprintf(file->file, format, ap);
+}
+
+void
+aoview_file_printf(struct aoview_file *file, char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       aoview_file_vprintf(file, format, ap);
+       va_end(ap);
+}
+
+struct aoview_file *
+aoview_file_new(char *ext)
+{
+       struct aoview_file      *file;
+
+       file = calloc (1, sizeof (struct aoview_file));
+       if (!file)
+               return NULL;
+       file->ext = strdup(ext);
+       if (!file->ext) {
+               free(file);
+               return NULL;
+       }
+       return file;
+}
+
+void
+aoview_file_destroy(struct aoview_file *file)
+{
+       if (file->file)
+               fclose(file->file);
+       if (file->name)
+               free(file->name);
+       free(file->ext);
+       free(file);
+}
+
+void
+aoview_file_set_serial(struct aoview_file *file, int serial)
+{
+       if (serial != file->serial)
+               aoview_file_finish(file);
+       file->serial = serial;
+}
+
+int
+aoview_file_get_serial(struct aoview_file *file)
+{
+       return file->serial;
+}
+
+void
+aoview_file_init(GladeXML *xml)
+{
+       GConfClient     *gconf_client;
+       char            *file_dir = NULL;
+       GtkFileChooser  *file_chooser_dialog;
+       GtkWidget       *file_configure_ok;
+
+       g_type_init();
+       gconf_client = gconf_client_get_default();
+       if (gconf_client)
+       {
+               file_dir = gconf_client_get_string(gconf_client,
+                                                  ALTOS_DIR_PATH,
+                                                  NULL);
+               g_object_unref(G_OBJECT(gconf_client));
+       }
+       if (!file_dir) {
+               aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR);
+               aoview_file_save_conf();
+       } else {
+               aoview_file_dir = strdup(file_dir);
+       }
+
+       file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog"));
+       assert(file_chooser_dialog);
+       gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir);
+
+       file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok");
+       assert(file_configure_ok);
+
+       g_signal_connect(G_OBJECT(file_configure_ok), "clicked",
+                        G_CALLBACK(aoview_file_configure),
+                        file_chooser_dialog);
+
+
+       file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog"));
+       assert(file_fail_dialog);
+}
diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c
new file mode 100644 (file)
index 0000000..e1b7589
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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 <stdio.h>
+#include <flite/flite.h>
+#include "aoview.h"
+#include <alsa/asoundlib.h>
+
+cst_voice *register_cmu_us_kal();
+static cst_voice *voice;
+
+static FILE *pipe_write;
+static GThread *aoview_flite_thread;
+
+static snd_pcm_t       *alsa_handle;
+
+gpointer
+aoview_flite_task(gpointer data)
+{
+       FILE            *input = data;
+       char            line[1024];
+       cst_wave        *wave;
+       int             rate;
+       int             channels;
+       int             err;
+       char            *samples;
+       int             num_samples;
+
+       err = snd_pcm_open(&alsa_handle, "default",
+                          SND_PCM_STREAM_PLAYBACK, 0);
+       if (err >= 0)
+       {
+               if (err < 0) {
+                       snd_pcm_close(alsa_handle);
+                       alsa_handle = 0;
+               }
+       }
+       rate = 0;
+       channels = 0;
+       while (fgets(line, sizeof (line) - 1, input) != NULL) {
+               if (!alsa_handle)
+                       continue;
+               wave = flite_text_to_wave(line, voice);
+               if (wave->sample_rate != rate ||
+                   wave->num_channels != channels)
+               {
+                       rate = wave->sample_rate;
+                       channels = wave->num_channels;
+                       err = snd_pcm_set_params(alsa_handle,
+                                                SND_PCM_FORMAT_S16,
+                                                SND_PCM_ACCESS_RW_INTERLEAVED,
+                                                channels,
+                                                rate,
+                                                1,
+                                                100000);
+                       if (err < 0)
+                               fprintf(stderr, "alsa set_params error %s\n",
+                                       strerror(-err));
+               }
+               err = snd_pcm_prepare(alsa_handle);
+               if (err < 0)
+                       fprintf(stderr, "alsa pcm_prepare error %s\n",
+                               strerror(-err));
+               samples = (char *) wave->samples;
+               num_samples = wave->num_samples;
+               while (num_samples > 0) {
+                       err = snd_pcm_writei(alsa_handle,
+                                            samples, num_samples);
+                       if (err <= 0) {
+                               fprintf(stderr, "alsa write error %s\n",
+                                       strerror(-err));
+                               break;
+                       }
+                       num_samples -= err;
+                       samples += err * 2 * channels;
+               }
+               snd_pcm_drain(alsa_handle);
+               delete_wave(wave);
+       }
+       snd_pcm_close(alsa_handle);
+       alsa_handle = 0;
+       return NULL;
+}
+
+void
+aoview_flite_stop(void)
+{
+       int status;
+       if (pipe_write) {
+               fclose(pipe_write);
+               pipe_write = NULL;
+       }
+       if (aoview_flite_thread) {
+               g_thread_join(aoview_flite_thread);
+               aoview_flite_thread = NULL;
+       }
+}
+
+FILE *
+aoview_flite_start(void)
+{
+       static once;
+       int     p[2];
+       GError  *error;
+       FILE    *pipe_read;
+
+       if (!once) {
+               flite_init();
+               voice = register_cmu_us_kal();
+               if (!voice) {
+                       perror("register voice");
+                       exit(1);
+               }
+       }
+       aoview_flite_stop();
+       pipe(p);
+       pipe_read = fdopen(p[0], "r");
+       pipe_write = fdopen(p[1], "w");
+       g_thread_create(aoview_flite_task, pipe_read, TRUE, &error);
+       return pipe_write;
+}
diff --git a/ao-tools/ao-view/aoview_label.c b/ao-tools/ao-view/aoview_label.c
new file mode 100644 (file)
index 0000000..2431362
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 struct {
+       char            *name;
+       char            *initial_value;
+       GtkLabel        *widget;
+} label_widgets[] = {
+       { "height_label", "Height (m)", NULL },
+       { "state_label", "State", NULL },
+       { "rssi_label", "RSSI (dBm)", NULL },
+       { "speed_label", "Speed (m/s)", NULL },
+       { "height_value", "0", NULL },
+       { "state_value", "pad", NULL },
+       { "rssi_value", "-50", NULL },
+       { "speed_value", "0", NULL },
+};
+
+static void
+aoview_label_assign(GtkLabel *widget, char *value)
+{
+       char    *markup;
+
+       markup = g_markup_printf_escaped("<span font_weight=\"bold\" size=\"xx-large\">%s</span>", value);
+       gtk_label_set_markup(widget, markup);
+       g_free(markup);
+}
+
+void
+aoview_label_show(struct aostate *state)
+{
+       char    line[1024];
+       sprintf(line, "%d", state->height);
+       aoview_label_assign(label_widgets[4].widget, line);
+
+       aoview_label_assign(label_widgets[5].widget, state->data.state);
+
+       sprintf(line, "%d", state->data.rssi);
+       aoview_label_assign(label_widgets[6].widget, line);
+
+       if (state->ascent)
+               sprintf(line, "%6.0f", fabs(state->speed));
+       else
+               sprintf(line, "%6.0f", fabs(state->baro_speed));
+       aoview_label_assign(label_widgets[7].widget, line);
+}
+
+void
+aoview_label_init(GladeXML *xml)
+{
+       int i;
+       for (i = 0; i < sizeof(label_widgets)/sizeof(label_widgets[0]); i++) {
+               label_widgets[i].widget = GTK_LABEL(glade_xml_get_widget(xml, label_widgets[i].name));
+               aoview_label_assign(label_widgets[i].widget, label_widgets[i].initial_value);
+               assert(label_widgets[i].widget);
+       }
+}
diff --git a/ao-tools/ao-view/aoview_log.c b/ao-tools/ao-view/aoview_log.c
new file mode 100644 (file)
index 0000000..1b89c28
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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 struct aoview_file      *aoview_log;
+
+void
+aoview_log_new(void)
+{
+       aoview_file_finish(aoview_log);
+       aoview_state_new();
+}
+
+void
+aoview_log_set_serial(int serial)
+{
+       aoview_file_set_serial(aoview_log, serial);
+}
+
+int
+aoview_log_get_serial(void)
+{
+       return aoview_file_get_serial(aoview_log);
+}
+
+void
+aoview_log_printf(char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       aoview_file_vprintf(aoview_log, format, ap);
+       va_end(ap);
+}
+
+static void
+aoview_log_new_item(GtkWidget *widget, gpointer data)
+{
+       aoview_file_finish(aoview_log);
+}
+
+void
+aoview_log_init(GladeXML *xml)
+{
+       GtkWidget       *log_new;
+
+       aoview_log = aoview_file_new("telem");
+       assert(aoview_log);
+
+       log_new = glade_xml_get_widget(xml, "log_new");
+       assert(log_new);
+       g_signal_connect(G_OBJECT(log_new), "activate",
+                        G_CALLBACK(aoview_log_new_item),
+                        NULL);
+}
diff --git a/ao-tools/ao-view/aoview_main.c b/ao-tools/ao-view/aoview_main.c
new file mode 100644 (file)
index 0000000..64c1c02
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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 const char aoview_glade[] = {
+#include "aoview_glade.h"
+};
+
+static void usage(void) {
+       printf("aoview [--device|-d device_file]");
+       exit(1);
+}
+
+static void destroy_event(GtkWidget *widget, gpointer data)
+{
+       gtk_main_quit();
+}
+
+extern int _Xdebug;
+char *aoview_tty = NULL;
+
+int main(int argc, char **argv)
+{
+       GladeXML *xml = NULL;
+       GtkWidget *mainwindow;
+       GtkAboutDialog *about_dialog;
+
+       static struct option long_options[] = {
+               { "tty", 1, 0, 'T'},
+               { "sync", 0, 0, 's'},
+               { 0, 0, 0, 0 }
+       };
+       for (;;) {
+               int c, temp;
+
+               c = getopt_long_only(argc, argv, "sT:", long_options, &temp);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'T':
+                       aoview_tty = optarg;
+                       break;
+               case 's':
+                       _Xdebug = 1;
+                       break;
+               default:
+                       usage();
+               }
+       }
+
+       g_thread_init(NULL);
+       gtk_init(&argc, &argv);
+       glade_init();
+
+       xml = glade_xml_new_from_buffer(aoview_glade, sizeof (aoview_glade), NULL, NULL);
+
+       /* connect the signals in the interface */
+       glade_xml_signal_autoconnect(xml);
+
+       /* Hook up the close button. */
+       mainwindow = glade_xml_get_widget(xml, "aoview");
+       assert(mainwindow);
+
+       g_signal_connect (G_OBJECT(mainwindow), "destroy",
+           G_CALLBACK(destroy_event), NULL);
+
+       about_dialog = GTK_ABOUT_DIALOG(glade_xml_get_widget(xml, "about_dialog"));
+       assert(about_dialog);
+       gtk_about_dialog_set_version(about_dialog, AOVIEW_VERSION);
+
+       aoview_voice_init(xml);
+
+       aoview_dev_dialog_init(xml);
+
+       aoview_state_init(xml);
+
+       aoview_file_init(xml);
+
+       aoview_log_init(xml);
+
+       aoview_table_init(xml);
+
+       aoview_eeprom_init(xml);
+
+       aoview_replay_init(xml);
+
+       aoview_label_init(xml);
+
+       if (aoview_tty) {
+               if (!aoview_monitor_connect(aoview_tty)) {
+                       perror(aoview_tty);
+                       exit(1);
+               }
+       }
+       aoview_voice_speak("rocket flight monitor ready\n");
+
+       gtk_main();
+
+       return 0;
+}
diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c
new file mode 100644 (file)
index 0000000..8564014
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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 struct aoview_serial *monitor_serial;
+
+#define MONITOR_LEN    1024
+
+static char    monitor_line[MONITOR_LEN + 1];
+static int     monitor_pos;
+
+void
+aoview_monitor_disconnect(void)
+{
+       if (monitor_serial) {
+               aoview_serial_close(monitor_serial);
+               monitor_serial = NULL;
+       }
+       aoview_log_new();
+}
+
+static void
+aoview_parse_string(char *target, int len, char *source)
+{
+       strncpy(target, source, len-1);
+       target[len-1] = '\0';
+}
+
+static void
+aoview_parse_int(int *target, char *source)
+{
+       *target = strtol(source, NULL, 0);
+}
+
+static void
+aoview_parse_hex(int *target, char *source)
+{
+       *target = strtol(source, NULL, 16);
+}
+
+static void
+aoview_parse_pos(double *target, char *source)
+{
+       int     deg;
+       double  min;
+       char    dir;
+       double  r;
+
+       if (sscanf(source, "%d°%lf'%c", &deg, &min, &dir) != 3) {
+               *target = 0;
+               return;
+       }
+       r = deg + min / 60.0;
+       if (dir == 'S' || dir == 'W')
+               r = -r;
+       *target = r;
+}
+
+#define PARSE_MAX_WORDS        256
+
+gboolean
+aoview_monitor_parse(const char *input_line)
+{
+       char *saveptr;
+       char *words[PARSE_MAX_WORDS];
+       int nword;
+       char line_buf[8192], *line;
+       struct aodata   data;
+       int     tracking_pos;
+
+       /* avoid smashing our input parameter */
+       strncpy (line_buf, input_line, sizeof (line_buf)-1);
+       line_buf[sizeof(line_buf) - 1] = '\0';
+       line = line_buf;
+       for (nword = 0; nword < PARSE_MAX_WORDS; nword++) {
+               words[nword] = strtok_r(line, " \t\n", &saveptr);
+               line = NULL;
+               if (words[nword] == NULL)
+                       break;
+       }
+       if (nword < 36)
+               return FALSE;
+       if (strcmp(words[0], "CALL") != 0)
+               return FALSE;
+       aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]);
+       aoview_parse_int(&data.serial, words[3]);
+
+       aoview_parse_int(&data.rssi, words[5]);
+       aoview_parse_string(data.state, sizeof (data.state), words[9]);
+       aoview_parse_int(&data.tick, words[10]);
+       aoview_parse_int(&data.accel, words[12]);
+       aoview_parse_int(&data.pres, words[14]);
+       aoview_parse_int(&data.temp, words[16]);
+       aoview_parse_int(&data.batt, words[18]);
+       aoview_parse_int(&data.drogue, words[20]);
+       aoview_parse_int(&data.main, words[22]);
+       aoview_parse_int(&data.flight_accel, words[24]);
+       aoview_parse_int(&data.ground_accel, words[26]);
+       aoview_parse_int(&data.flight_vel, words[28]);
+       aoview_parse_int(&data.flight_pres, words[30]);
+       aoview_parse_int(&data.ground_pres, words[32]);
+       aoview_parse_int(&data.gps.nsat, words[34]);
+       if (strcmp (words[36], "unlocked") == 0) {
+               data.gps.gps_connected = 1;
+               data.gps.gps_locked = 0;
+               data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0;
+               data.gps.lat = data.gps.lon = 0;
+               data.gps.alt = 0;
+               tracking_pos = 37;
+       } else if (nword >= 40) {
+               data.gps.gps_locked = 1;
+               data.gps.gps_connected = 1;
+               sscanf(words[36], "%d:%d:%d", &data.gps.gps_time.hour, &data.gps.gps_time.minute, &data.gps.gps_time.second);
+               aoview_parse_pos(&data.gps.lat, words[37]);
+               aoview_parse_pos(&data.gps.lon, words[38]);
+               sscanf(words[39], "%dm", &data.gps.alt);
+               tracking_pos = 46;
+       } else {
+               data.gps.gps_connected = 0;
+               data.gps.gps_locked = 0;
+               data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0;
+               data.gps.lat = data.gps.lon = 0;
+               data.gps.alt = 0;
+               tracking_pos = -1;
+       }
+       if (nword >= 46) {
+               data.gps.gps_extended = 1;
+               sscanf(words[40], "%lfm/s", &data.gps.ground_speed);
+               sscanf(words[41], "%d", &data.gps.course);
+               sscanf(words[42], "%lfm/s", &data.gps.climb_rate);
+               sscanf(words[43], "%lf", &data.gps.hdop);
+               sscanf(words[44], "%d", &data.gps.h_error);
+               sscanf(words[45], "%d", &data.gps.v_error);
+       } else {
+               data.gps.gps_extended = 0;
+               data.gps.ground_speed = 0;
+               data.gps.course = 0;
+               data.gps.climb_rate = 0;
+               data.gps.hdop = 0;
+               data.gps.h_error = 0;
+               data.gps.v_error = 0;
+       }
+       if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) {
+               int     c, n, pos;
+               aoview_parse_int(&n, words[tracking_pos + 1]);
+               pos = tracking_pos + 2;
+               if (nword >= pos + n * 3) {
+                       data.gps_tracking.channels = n;
+                       for (c = 0; c < n; c++) {
+                               aoview_parse_int(&data.gps_tracking.sats[c].svid,
+                                                words[pos + 0]);
+                               aoview_parse_hex(&data.gps_tracking.sats[c].state,
+                                                words[pos + 1]);
+                               aoview_parse_int(&data.gps_tracking.sats[c].c_n0,
+                                                words[pos + 2]);
+                               pos += 3;
+                       }
+               } else {
+                       data.gps_tracking.channels = 0;
+               }
+       } else {
+               data.gps_tracking.channels = 0;
+       }
+       aoview_state_notify(&data);
+       return TRUE;
+}
+
+static void
+aoview_monitor_callback(gpointer user_data,
+                       struct aoview_serial *serial,
+                       gint revents)
+{
+       int     c;
+
+       if (revents & (G_IO_HUP|G_IO_ERR)) {
+               aoview_monitor_disconnect();
+               return;
+       }
+       if (revents & G_IO_IN) {
+               for (;;) {
+                       c = aoview_serial_getc(serial);
+                       if (c == -1)
+                               break;
+                       if (c == '\r')
+                               continue;
+                       if (c == '\n') {
+                               monitor_line[monitor_pos] = '\0';
+                               if (monitor_pos) {
+                                       if (aoview_monitor_parse(monitor_line)) {
+                                               aoview_log_set_serial(aostate.data.serial);
+                                               if (aoview_log_get_serial())
+                                                       aoview_log_printf ("%s\n", monitor_line);
+                                       }
+                               }
+                               monitor_pos = 0;
+                       } else if (monitor_pos < MONITOR_LEN)
+                               monitor_line[monitor_pos++] = c;
+               }
+       }
+}
+
+gboolean
+aoview_monitor_connect(char *tty)
+{
+       aoview_monitor_disconnect();
+       monitor_serial = aoview_serial_open(tty);
+       if (!monitor_serial)
+               return FALSE;
+       aoview_table_clear();
+       aoview_state_reset();
+       aoview_serial_set_callback(monitor_serial,
+                                  aoview_monitor_callback);
+       return TRUE;
+}
diff --git a/ao-tools/ao-view/aoview_replay.c b/ao-tools/ao-view/aoview_replay.c
new file mode 100644 (file)
index 0000000..da7b5d6
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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 GtkFileChooser  *replay_dialog;
+static GtkWidget       *replay_ok;
+static FILE            *replay_file;
+static int             replay_tick;
+
+static int
+find_tick(char *line, gboolean *is_pad)
+{
+       char    *state = strstr(line, "STATE");
+       if (!state)
+               return -1;
+       state = strchr(state, ' ');
+       if (!state)
+               return -1;
+       while (*state == ' ')
+               state++;
+       *is_pad = strncmp(state, "pad", 3) == 0;
+       while (*state && !isdigit(*state))
+               state++;
+       return atoi(state);
+}
+
+static void
+aoview_replay_close(void)
+{
+       if (replay_file) {
+               fclose(replay_file);
+               replay_file = NULL;
+       }
+}
+
+static char    replay_line[1024];
+
+static gboolean
+aoview_replay_read(gpointer data);
+
+static gboolean
+aoview_replay_execute(gpointer data)
+{
+       aoview_monitor_parse(replay_line);
+       g_idle_add(aoview_replay_read, NULL);
+       return FALSE;
+}
+
+static gboolean
+aoview_replay_read(gpointer data)
+{
+       int             tick;
+       gboolean        is_pad;
+
+       if (!replay_file)
+               return FALSE;
+       if (fgets(replay_line, sizeof (replay_line), replay_file)) {
+               tick = find_tick(replay_line, &is_pad);
+               if (tick >= 0 && replay_tick >= 0 && !is_pad) {
+                       while (tick < replay_tick)
+                               tick += 65536;
+                       g_timeout_add((tick - replay_tick) * 10,
+                                     aoview_replay_execute,
+                                     NULL);
+               } else {
+                       aoview_replay_execute(NULL);
+               }
+               replay_tick = tick;
+       } else {
+               aoview_replay_close();
+       }
+       return FALSE;
+}
+
+static void
+aoview_replay_open(GtkWidget *widget, gpointer data)
+{
+       char            *replay_file_name;
+       GtkWidget       *dialog;
+
+       aoview_replay_close();
+       replay_file_name = gtk_file_chooser_get_filename(replay_dialog);
+       replay_file = fopen(replay_file_name, "r");
+       if (!replay_file) {
+               dialog = gtk_message_dialog_new(GTK_WINDOW(replay_dialog),
+                                               GTK_DIALOG_DESTROY_WITH_PARENT,
+                                               GTK_MESSAGE_ERROR,
+                                               GTK_BUTTONS_CLOSE,
+                                               "Error loading file '%s': %s",
+                                               replay_file_name, g_strerror(errno));
+               gtk_dialog_run(GTK_DIALOG(dialog));
+               gtk_widget_destroy(dialog);
+       } else {
+               replay_tick = -1;
+               aoview_state_reset();
+               aoview_replay_read(NULL);
+       }
+       gtk_widget_hide(GTK_WIDGET(replay_dialog));
+}
+
+void
+aoview_replay_init(GladeXML *xml)
+{
+       GtkFileFilter   *telem_filter;
+       GtkFileFilter   *all_filter;
+       GtkFileFilter   *log_filter;
+
+       telem_filter = gtk_file_filter_new();
+       gtk_file_filter_add_pattern(telem_filter, "*.telem");
+       gtk_file_filter_set_name(telem_filter, "Telemetry Files");
+
+       log_filter = gtk_file_filter_new();
+       gtk_file_filter_add_pattern(log_filter, "*.log");
+       gtk_file_filter_set_name(log_filter, "Log Files");
+
+       all_filter = gtk_file_filter_new();
+       gtk_file_filter_add_pattern(all_filter, "*");
+       gtk_file_filter_set_name(all_filter, "All Files");
+
+       replay_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "ao_replay_dialog"));
+       assert(replay_dialog);
+       gtk_file_chooser_set_current_folder(replay_dialog, aoview_file_dir);
+       gtk_file_chooser_add_filter(replay_dialog, telem_filter);
+       gtk_file_chooser_add_filter(replay_dialog, log_filter);
+       gtk_file_chooser_add_filter(replay_dialog, all_filter);
+
+       replay_ok = glade_xml_get_widget(xml, "ao_replay_ok");
+       assert(replay_ok);
+       g_signal_connect(G_OBJECT(replay_ok), "clicked",
+                        G_CALLBACK(aoview_replay_open),
+                        replay_dialog);
+}
diff --git a/ao-tools/ao-view/aoview_serial.c b/ao-tools/ao-view/aoview_serial.c
new file mode 100644 (file)
index 0000000..29038b7
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * 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"
+#include <termios.h>
+
+#define AOVIEW_SERIAL_IN_BUF   64
+#define AOVIEW_SERIAL_OUT_BUF  64
+
+struct aoview_buf {
+       char            *buf;
+       int             off;
+       int             count;
+       int             size;
+};
+
+static int
+aoview_buf_write(struct aoview_buf *buf, char *data, int len)
+{
+       if (buf->count + len > buf->size) {
+               int     new_size = buf->size * 2;
+               if (new_size == 0)
+                       new_size = 1024;
+               if (buf->buf)
+                       buf->buf = realloc (buf->buf, new_size);
+               else
+                       buf->buf = malloc (new_size);
+               buf->size = new_size;
+       }
+       memcpy(buf->buf + buf->count, data, len);
+       buf->count += len;
+       return len;
+}
+
+static int
+aoview_buf_read(struct aoview_buf *buf, char *data, int len)
+{
+       if (len > buf->count - buf->off)
+               len = buf->count - buf->off;
+       memcpy (data, buf->buf + buf->off, len);
+       buf->off += len;
+       if (buf->off == buf->count)
+               buf->off = buf->count = 0;
+       return len;
+}
+
+static int
+aoview_buf_getc(struct aoview_buf *buf)
+{
+       char    b;
+       int     r;
+
+       r = aoview_buf_read(buf, &b, 1);
+       if (r == 1)
+               return (int) b;
+       return -1;
+}
+
+static void
+aoview_buf_flush(struct aoview_buf *buf, int fd)
+{
+       int     ret;
+
+       if (buf->count > buf->off) {
+               ret = write(fd, buf->buf + buf->off, buf->count - buf->off);
+               if (ret > 0) {
+                       buf->off += ret;
+                       if (buf->off == buf->count)
+                               buf->off = buf->count = 0;
+               }
+       }
+}
+
+static void
+aoview_buf_fill(struct aoview_buf *buf, int fd)
+{
+       int ret;
+
+       while (buf->count >= buf->size) {
+               int new_size = buf->size * 2;
+               buf->buf = realloc (buf->buf, new_size);
+               buf->size = new_size;
+       }
+
+       ret = read(fd, buf->buf + buf->count, buf->size - buf->count);
+       if (ret > 0)
+               buf->count += ret;
+}
+
+static void
+aoview_buf_init(struct aoview_buf *buf)
+{
+       buf->buf = malloc (buf->size = 1024);
+       buf->count = 0;
+}
+
+static void
+aoview_buf_fini(struct aoview_buf *buf)
+{
+       free(buf->buf);
+}
+
+struct aoview_serial {
+       GSource                 source;
+       int                     fd;
+       struct termios          save_termios;
+       struct aoview_buf       in_buf;
+       struct aoview_buf       out_buf;
+       GPollFD                 poll_fd;
+};
+
+
+void
+aoview_serial_printf(struct aoview_serial *serial, char *format, ...)
+{
+       char    buf[1024];
+       va_list ap;
+       int     ret;
+
+       /* sprintf to a local buffer */
+       va_start(ap, format);
+       ret = vsnprintf(buf, sizeof(buf), format, ap);
+       va_end(ap);
+       if (ret > sizeof(buf)) {
+               fprintf(stderr, "printf overflow for format %s\n",
+                       format);
+       }
+
+       /* flush local buffer to the wire */
+       aoview_buf_write(&serial->out_buf, buf, ret);
+       aoview_buf_flush(&serial->out_buf, serial->fd);
+}
+
+int
+aoview_serial_read(struct aoview_serial *serial, char *buf, int len)
+{
+       return aoview_buf_read(&serial->in_buf, buf, len);
+}
+
+int
+aoview_serial_getc(struct aoview_serial *serial)
+{
+       return aoview_buf_getc(&serial->in_buf);
+}
+
+static gboolean
+serial_prepare(GSource *source, gint *timeout)
+{
+       struct aoview_serial *serial = (struct aoview_serial *) source;
+       *timeout = -1;
+
+       if (serial->out_buf.count)
+               serial->poll_fd.events |= G_IO_OUT;
+       else
+               serial->poll_fd.events &= ~G_IO_OUT;
+       return FALSE;
+}
+
+static gboolean
+serial_check(GSource *source)
+{
+       struct aoview_serial *serial = (struct aoview_serial *) source;
+       gint revents = serial->poll_fd.revents;
+
+       if (revents & G_IO_NVAL)
+               return FALSE;
+       if (revents & G_IO_IN)
+               return TRUE;
+       if (revents & G_IO_OUT)
+               return TRUE;
+       return FALSE;
+}
+
+static gboolean
+serial_dispatch(GSource *source,
+               GSourceFunc callback,
+               gpointer user_data)
+{
+       struct aoview_serial *serial = (struct aoview_serial *) source;
+       aoview_serial_callback func = (aoview_serial_callback) callback;
+       gint revents = serial->poll_fd.revents;
+
+       if (revents & G_IO_IN)
+               aoview_buf_fill(&serial->in_buf, serial->fd);
+
+       if (revents & G_IO_OUT)
+               aoview_buf_flush(&serial->out_buf, serial->fd);
+
+       if (func)
+               (*func)(user_data, serial, revents);
+       return TRUE;
+}
+
+static void
+serial_finalize(GSource *source)
+{
+       struct aoview_serial *serial = (struct aoview_serial *) source;
+
+       aoview_buf_fini(&serial->in_buf);
+       aoview_buf_fini(&serial->out_buf);
+       tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios);
+       close (serial->fd);
+}
+
+static GSourceFuncs serial_funcs = {
+       serial_prepare,
+       serial_check,
+       serial_dispatch,
+       serial_finalize
+};
+
+struct aoview_serial *
+aoview_serial_open(const char *tty)
+{
+       struct aoview_serial    *serial;
+       struct termios  termios;
+
+       serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial));
+       aoview_buf_init(&serial->in_buf);
+       aoview_buf_init(&serial->out_buf);
+       serial->fd = open (tty, O_RDWR | O_NONBLOCK);
+       if (serial->fd < 0) {
+               g_source_destroy(&serial->source);
+               return NULL;
+       }
+       tcgetattr(serial->fd, &termios);
+       serial->save_termios = termios;
+       cfmakeraw(&termios);
+       tcsetattr(serial->fd, TCSAFLUSH, &termios);
+
+       aoview_serial_printf(serial, "E 0\n");
+       tcdrain(serial->fd);
+       usleep(15*1000);
+       tcflush(serial->fd, TCIFLUSH);
+       serial->poll_fd.fd = serial->fd;
+       serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
+       g_source_attach(&serial->source, NULL);
+       g_source_add_poll(&serial->source,&serial->poll_fd);
+       aoview_serial_set_callback(serial, NULL);
+       return serial;
+}
+
+void
+aoview_serial_close(struct aoview_serial *serial)
+{
+       g_source_remove_poll(&serial->source, &serial->poll_fd);
+       close(serial->fd);
+       g_source_destroy(&serial->source);
+}
+
+void
+aoview_serial_set_callback(struct aoview_serial *serial,
+                          aoview_serial_callback func)
+{
+       g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL);
+}
diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c
new file mode 100644 (file)
index 0000000..f75066d
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * 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"
+#include <math.h>
+
+static inline double sqr(double a) { return a * a; };
+
+static void
+aoview_great_circle (double start_lat, double start_lon,
+                    double end_lat, double end_lon,
+                    double *dist, double *bearing)
+{
+       const double rad = M_PI / 180;
+       const double earth_radius = 6371.2 * 1000;      /* in meters */
+       double lat1 = rad * start_lat;
+       double lon1 = rad * -start_lon;
+       double lat2 = rad * end_lat;
+       double lon2 = rad * -end_lon;
+
+       double d_lat = lat2 - lat1;
+       double d_lon = lon2 - lon1;
+
+       /* From http://en.wikipedia.org/wiki/Great-circle_distance */
+       double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) +
+                         sqr(cos(lat1) * sin(lat2) -
+                             sin(lat1) * cos(lat2) * cos(d_lon)));
+       double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon);
+       double d = atan2(vdn,vdd);
+       double course;
+
+       if (cos(lat1) < 1e-20) {
+               if (lat1 > 0)
+                       course = M_PI;
+               else
+                       course = -M_PI;
+       } else {
+               if (d < 1e-10)
+                       course = 0;
+               else
+                       course = acos((sin(lat2)-sin(lat1)*cos(d)) /
+                                     (sin(d)*cos(lat1)));
+               if (sin(lon2-lon1) > 0)
+                       course = 2 * M_PI-course;
+       }
+       *dist = d * earth_radius;
+       *bearing = course * 180/M_PI;
+}
+
+static void
+aoview_state_add_deg(int column, char *label, double deg, char pos, char neg)
+{
+       double  int_part;
+       double  min;
+       char    sign = pos;
+
+       if (deg < 0) {
+               deg = -deg;
+               sign = neg;
+       }
+       int_part = floor (deg);
+       min = (deg - int_part) * 60.0;
+       aoview_table_add_row(column, label, "%d°%lf'%c",
+                            (int) int_part, min, sign);
+
+}
+
+static char *ascent_states[] = {
+       "boost",
+       "fast",
+       "coast",
+       0,
+};
+
+static double
+aoview_time(void)
+{
+       struct timespec now;
+
+       clock_gettime(CLOCK_MONOTONIC, &now);
+       return (double) now.tv_sec + (double) now.tv_nsec / 1.0e9;
+}
+
+/*
+ * Fill out the derived data fields
+ */
+static void
+aoview_state_derive(struct aodata *data, struct aostate *state)
+{
+       int     i;
+       double  new_height;
+       double  height_change;
+       double  time_change;
+       int     tick_count;
+
+       state->report_time = aoview_time();
+
+       state->prev_data = state->data;
+       state->prev_npad = state->npad;
+       state->data = *data;
+       tick_count = data->tick;
+       if (tick_count < state->prev_data.tick)
+               tick_count += 65536;
+       time_change = (tick_count - state->prev_data.tick) / 100.0;
+
+       state->ground_altitude = aoview_pres_to_altitude(data->ground_pres);
+       new_height = aoview_pres_to_altitude(data->flight_pres) - state->ground_altitude;
+       height_change = new_height - state->height;
+       state->height = new_height;
+       if (time_change)
+               state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0;
+       state->acceleration = (data->ground_accel - data->flight_accel) / 27.0;
+       state->speed = data->flight_vel / 2700.0;
+       state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01;
+       state->drogue_sense = data->drogue / 32767.0 * 15.0;
+       state->main_sense = data->main / 32767.0 * 15.0;
+       state->battery = data->batt / 32767.0 * 5.0;
+       if (!strcmp(data->state, "pad")) {
+               if (data->gps.gps_locked && data->gps.nsat >= 4) {
+                       state->npad++;
+                       state->pad_lat_total += data->gps.lat;
+                       state->pad_lon_total += data->gps.lon;
+                       state->pad_alt_total += data->gps.alt;
+                       if (state->npad > 1) {
+                               state->pad_lat = (state->pad_lat * 31 + data->gps.lat) / 32.0;
+                               state->pad_lon = (state->pad_lon * 31 + data->gps.lon) / 32.0;
+                               state->pad_alt = (state->pad_alt * 31 + data->gps.alt) / 32.0;
+                       } else {
+                               state->pad_lat = data->gps.lat;
+                               state->pad_lon = data->gps.lon;
+                               state->pad_alt = data->gps.alt;
+                       }
+               }
+       }
+       state->ascent = FALSE;
+       for (i = 0; ascent_states[i]; i++)
+               if (!strcmp(data->state, ascent_states[i]))
+                       state->ascent = TRUE;
+
+       /* Only look at accelerometer data on the way up */
+       if (state->ascent && state->acceleration > state->max_acceleration)
+               state->max_acceleration = state->acceleration;
+       if (state->ascent && state->speed > state->max_speed)
+               state->max_speed = state->speed;
+
+       if (state->height > state->max_height)
+               state->max_height = state->height;
+       state->gps.gps_locked = data->gps.gps_locked;
+       state->gps.gps_connected = data->gps.gps_connected;
+       if (data->gps.gps_locked) {
+               state->gps = data->gps;
+               state->gps_valid = 1;
+               if (state->npad)
+                       aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon,
+                                           &state->distance, &state->bearing);
+       }
+       if (data->gps_tracking.channels)
+               state->gps_tracking = data->gps_tracking;
+       if (state->npad) {
+               state->gps_height = state->gps.alt - state->pad_alt;
+       } else {
+               state->gps_height = 0;
+       }
+}
+
+void
+aoview_speak_state(struct aostate *state)
+{
+       if (strcmp(state->data.state, state->prev_data.state)) {
+               aoview_voice_speak("%s\n", state->data.state);
+               if (!strcmp(state->data.state, "drogue"))
+                       aoview_voice_speak("apogee %d meters\n",
+                                          (int) state->max_height);
+               if (!strcmp(state->prev_data.state, "boost"))
+                       aoview_voice_speak("max speed %d meters per second\n",
+                                          (int) state->max_speed);
+       }
+       if (state->prev_npad < MIN_PAD_SAMPLES && state->npad >= MIN_PAD_SAMPLES)
+               aoview_voice_speak("g p s ready\n");
+}
+
+void
+aoview_speak_height(struct aostate *state)
+{
+       aoview_voice_speak("%d meters\n", state->height);
+}
+
+struct aostate aostate;
+
+static guint aostate_timeout;
+
+#define COMPASS_LIMIT(n)       ((n * 22.5) + 22.5/2)
+
+static char *compass_points[] = {
+       "north",
+       "north north east",
+       "north east",
+       "east north east",
+       "east",
+       "east south east",
+       "south east",
+       "south south east",
+       "south",
+       "south south west",
+       "south west",
+       "west south west",
+       "west",
+       "west north west",
+       "north west",
+       "north north west",
+};
+
+static char *
+aoview_compass_point(double bearing)
+{
+       int     i;
+       while (bearing < 0)
+               bearing += 360.0;
+       while (bearing >= 360.0)
+               bearing -= 360.0;
+
+       i = floor ((bearing - 22.5/2) / 22.5 + 0.5);
+       if (i < 0) i = 0;
+       if (i >= sizeof (compass_points) / sizeof (compass_points[0]))
+               i = 0;
+       return compass_points[i];
+}
+
+static gboolean
+aoview_state_timeout(gpointer data)
+{
+       double  now = aoview_time();
+
+       if (strlen(aostate.data.state) > 0 && strcmp(aostate.data.state, "pad") != 0)
+               aoview_speak_height(&aostate);
+       if (now - aostate.report_time >= 20 || !strcmp(aostate.data.state, "landed")) {
+               if (!aostate.ascent) {
+                       if (fabs(aostate.baro_speed) < 20 && aostate.height < 100)
+                               aoview_voice_speak("rocket landed safely\n");
+                       else
+                               aoview_voice_speak("rocket may have crashed\n");
+                       if (aostate.gps_valid) {
+                               aoview_voice_speak("rocket reported %s of pad distance %d meters\n",
+                                                  aoview_compass_point(aostate.bearing),
+                                                  (int) aostate.distance);
+                       }
+               }
+               aostate_timeout = 0;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+void
+aoview_state_reset(void)
+{
+       memset(&aostate, '\0', sizeof (aostate));
+}
+
+void
+aoview_state_notify(struct aodata *data)
+{
+       struct aostate *state = &aostate;
+       aoview_state_derive(data, state);
+       aoview_table_start();
+
+       if (state->npad >= MIN_PAD_SAMPLES)
+               aoview_table_add_row(0, "Ground state", "ready");
+       else
+               aoview_table_add_row(0, "Ground state", "waiting for gps (%d)",
+                                    MIN_PAD_SAMPLES - state->npad);
+       aoview_table_add_row(0, "Rocket state", "%s", state->data.state);
+       aoview_table_add_row(0, "Callsign", "%s", state->data.callsign);
+       aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial);
+
+       aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi);
+       aoview_table_add_row(0, "Height", "%6dm", state->height);
+       aoview_table_add_row(0, "Max height", "%6dm", state->max_height);
+       aoview_table_add_row(0, "Acceleration", "%7.1fm/s²", state->acceleration);
+       aoview_table_add_row(0, "Max acceleration", "%7.1fm/s²", state->max_acceleration);
+       aoview_table_add_row(0, "Speed", "%7.1fm/s", state->ascent ? state->speed : state->baro_speed);
+       aoview_table_add_row(0, "Max Speed", "%7.1fm/s", state->max_speed);
+       aoview_table_add_row(0, "Temperature", "%6.2f°C", state->temperature);
+       aoview_table_add_row(0, "Battery", "%5.2fV", state->battery);
+       aoview_table_add_row(0, "Drogue", "%5.2fV", state->drogue_sense);
+       aoview_table_add_row(0, "Main", "%5.2fV", state->main_sense);
+       aoview_table_add_row(0, "Pad altitude", "%dm", state->ground_altitude);
+       aoview_table_add_row(1, "Satellites", "%d", state->gps.nsat);
+       if (state->gps.gps_locked) {
+               aoview_table_add_row(1, "GPS", "locked");
+       } else if (state->gps.gps_connected) {
+               aoview_table_add_row(1, "GPS", "unlocked");
+       } else {
+               aoview_table_add_row(1, "GPS", "not available");
+       }
+       if (state->gps_valid) {
+               aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S');
+               aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W');
+               aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt);
+               aoview_table_add_row(1, "GPS height", "%d", state->gps_height);
+               aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d",
+                                    state->gps.gps_time.hour,
+                                    state->gps.gps_time.minute,
+                                    state->gps.gps_time.second);
+       }
+       if (state->gps.gps_extended) {
+               aoview_table_add_row(1, "GPS ground speed", "%7.1fm/s %d°",
+                                    state->gps.ground_speed,
+                                    state->gps.course);
+               aoview_table_add_row(1, "GPS climb rate", "%7.1fm/s",
+                                    state->gps.climb_rate);
+               aoview_table_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)",
+                                    state->gps.hdop, state->gps.h_error, state->gps.v_error);
+       }
+       if (state->npad) {
+               aoview_table_add_row(1, "Distance from pad", "%5.0fm", state->distance);
+               aoview_table_add_row(1, "Direction from pad", "%4.0f°", state->bearing);
+               aoview_state_add_deg(1, "Pad latitude", state->pad_lat, 'N', 'S');
+               aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W');
+               aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt);
+       }
+       if (state->gps.gps_connected) {
+               int     nsat_vis = 0;
+               int     nsat_locked = 0;
+               int     c;
+
+               for (c = 0; c < state->gps_tracking.channels; c++) {
+                       if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf)
+                               nsat_locked++;
+               }
+               aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels);
+               aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked);
+               for (c = 0; c < state->gps_tracking.channels; c++) {
+                       aoview_table_add_row(2, "Satellite id,state,C/N0",
+                                            "%3d,%02x,%2d%s",
+                                            state->gps_tracking.sats[c].svid,
+                                            state->gps_tracking.sats[c].state,
+                                            state->gps_tracking.sats[c].c_n0,
+                                            (state->gps_tracking.sats[c].state & 0xff) == 0xbf ?
+                                            " LOCKED" : "");
+               }
+       }
+       aoview_table_finish();
+       aoview_label_show(state);
+       aoview_speak_state(state);
+       if (!aostate_timeout && strcmp(state->data.state, "pad") != 0)
+               aostate_timeout = g_timeout_add_seconds(10, aoview_state_timeout, NULL);
+}
+
+void
+aoview_state_new(void)
+{
+}
+
+void
+aoview_state_init(GladeXML *xml)
+{
+       aoview_state_new();
+}
diff --git a/ao-tools/ao-view/aoview_table.c b/ao-tools/ao-view/aoview_table.c
new file mode 100644 (file)
index 0000000..e75ae67
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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 NCOL   3
+
+static GtkTreeView     *dataview[NCOL];
+static GtkListStore    *datalist[NCOL];
+
+void
+aoview_table_start(void)
+{
+       int col;
+       for (col = 0; col < NCOL; col++)
+               datalist[col] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+}
+
+void
+aoview_table_add_row(int col, 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[col], &iter);
+       gtk_list_store_set(datalist[col], &iter,
+                          0, label,
+                          1, buf,
+                          -1);
+}
+
+void
+aoview_table_finish(void)
+{
+       int     col;
+       for (col = 0; col < NCOL; col++) {
+               gtk_tree_view_set_model(dataview[col], GTK_TREE_MODEL(datalist[col]));
+               g_object_unref(G_OBJECT(datalist[col]));
+               gtk_tree_view_columns_autosize(dataview[col]);
+       }
+}
+
+void
+aoview_table_clear(void)
+{
+       int     col;
+       for (col = 0; col < NCOL; col++)
+               gtk_tree_view_set_model(dataview[col], NULL);
+}
+
+void
+aoview_table_init(GladeXML *xml)
+{
+       int     col;
+
+       for (col = 0; col < NCOL; col++) {
+               char    name[32];
+               sprintf(name, "dataview_%d", col);
+               dataview[col] = GTK_TREE_VIEW(glade_xml_get_widget(xml, name));
+               assert(dataview[col]);
+
+               aoview_add_plain_text_column(dataview[col], "Field", 0, 20);
+               aoview_add_plain_text_column(dataview[col], "Value", 1, 32);
+       }
+}
diff --git a/ao-tools/ao-view/aoview_util.c b/ao-tools/ao-view/aoview_util.c
new file mode 100644 (file)
index 0000000..6ea62ac
--- /dev/null
@@ -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;
+}
diff --git a/ao-tools/ao-view/aoview_voice.c b/ao-tools/ao-view/aoview_voice.c
new file mode 100644 (file)
index 0000000..24422df
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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"
+
+#if HAVE_FLITE
+#include <stdarg.h>
+
+FILE   *aoview_flite;
+
+void aoview_voice_open(void)
+{
+       int     err;
+
+       if (!aoview_flite)
+               aoview_flite = aoview_flite_start();
+}
+
+void aoview_voice_close(void)
+{
+       if (aoview_flite) {
+               aoview_flite_stop();
+               aoview_flite = NULL;
+       }
+}
+
+void aoview_voice_speak(char *format, ...)
+{
+       va_list ap;
+
+       if (aoview_flite) {
+               va_start(ap, format);
+               vfprintf(aoview_flite, format, ap);
+               fflush(aoview_flite);
+               va_end(ap);
+       }
+}
+
+#else
+void aoview_voice_open(void)
+{
+}
+
+void aoview_voice_close(void)
+{
+}
+
+void aoview_voice_speak(char *format, ...)
+{
+}
+#endif
+
+
+static GtkCheckMenuItem        *voice_enable;
+
+#define ALTOS_VOICE_PATH       "/apps/aoview/voice"
+
+static void
+aoview_voice_enable(GtkWidget *widget, gpointer data)
+{
+       gboolean        enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+       GError          *error;
+       GConfClient     *gconf_client;
+
+       if (enabled) {
+               aoview_voice_open();
+               aoview_voice_speak("enable voice\n");
+       } else {
+               aoview_voice_speak("disable voice\n");
+               aoview_voice_close();
+       }
+       gconf_client = gconf_client_get_default();
+       gconf_client_set_bool(gconf_client,
+                             ALTOS_VOICE_PATH,
+                             enabled,
+                             &error);
+}
+
+void
+aoview_voice_init(GladeXML *xml)
+{
+       gboolean        enabled;
+       GConfClient     *gconf_client;
+
+       voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable"));
+       assert(voice_enable);
+
+       gconf_client = gconf_client_get_default();
+       enabled = TRUE;
+       if (gconf_client)
+       {
+               GError  *error;
+
+               error = NULL;
+               enabled = gconf_client_get_bool(gconf_client,
+                                               ALTOS_VOICE_PATH,
+                                               &error);
+               if (error)
+                       enabled = TRUE;
+       }
+       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(voice_enable), enabled);
+       if (enabled)
+               aoview_voice_open();
+
+       g_signal_connect(G_OBJECT(voice_enable), "toggled",
+                        G_CALLBACK(aoview_voice_enable),
+                        voice_enable);
+}
diff --git a/ao-tools/ao-view/design b/ao-tools/ao-view/design
new file mode 100644 (file)
index 0000000..6ec2ea7
--- /dev/null
@@ -0,0 +1,27 @@
+Requirements:
+       real-time display of telemetry
+       off-line display of logged data
+       Logging of telemetry
+       Capture of logged data to disk
+
+Input data:
+       accelerometer
+       barometer
+       thermometer
+       gps
+       drogue and main continuity
+       battery voltage
+       time
+       reported flight state
+       reported events
+
+Computed data:
+       velocity (from accelerometer)
+       altitude
+       range
+       direction
+
+Displays:
+       numeric display of current rocket status
+       (graphics come later)
+       text message log
index 9584e216f3c7b4290d05078d76f85aeab3580345..f66ee0a99634a0e663393b549c3e618895f53944 100644 (file)
@@ -16,6 +16,9 @@ libao_tools_a_SOURCES = \
        ccdbg-state.c \
        cc-usb.c \
        cc-usb.h \
+       cc.h \
+       cc-usbdev.c \
+       cc-util.c \
        cc-bitbang.c \
        cc-bitbang.h \
        cp-usb-async.c \
diff --git a/ao-tools/lib/cc-usbdev.c b/ao-tools/lib/cc-usbdev.c
new file mode 100644 (file)
index 0000000..d8bb8b1
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 "cc.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *
+load_string(char *dir, char *file)
+{
+       char    *full = cc_fullname(dir, file);
+       char    line[4096];
+       char    *r;
+       FILE    *f;
+       int     rlen;
+
+       f = fopen(full, "r");
+       free(full);
+       if (!f)
+               return NULL;
+       r = fgets(line, sizeof (line), f);
+       fclose(f);
+       if (!r)
+               return NULL;
+       rlen = strlen(r);
+       if (r[rlen-1] == '\n')
+               r[rlen-1] = '\0';
+       return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+       char    *line;
+       char    *end;
+       long    i;
+
+       line = load_string(dir, file);
+       if (!line)
+               return -1;
+       i = strtol(line, &end, 16);
+       free(line);
+       if (end == line)
+               return -1;
+       return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+static char *
+usb_tty(char *sys)
+{
+       char *base;
+       int num_configs;
+       int config;
+       struct dirent **namelist;
+       int interface;
+       int num_interfaces;
+       char endpoint_base[20];
+       char *endpoint_full;
+       char *tty_dir;
+       int ntty;
+       char *tty;
+
+       base = cc_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 = cc_fullname(sys, endpoint_base);
+
+                       /* Check for tty:ttyACMx style names
+                        */
+                       ntty = scandir(endpoint_full, &namelist,
+                                      dir_filter_tty_colon,
+                                      alphasort);
+                       if (ntty > 0) {
+                               free(endpoint_full);
+                               tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+                               free(namelist);
+                               return tty;
+                       }
+
+                       /* Check for tty/ttyACMx style names
+                        */
+                       tty_dir = cc_fullname(endpoint_full, "tty");
+                       free(endpoint_full);
+                       ntty = scandir(tty_dir, &namelist,
+                                      dir_filter_tty,
+                                      alphasort);
+                       free (tty_dir);
+                       if (ntty > 0) {
+                               tty = cc_fullname("/dev", namelist[0]->d_name);
+                               free(namelist);
+                               return tty;
+                       }
+               }
+       }
+       return NULL;
+}
+
+static struct cc_usbdev *
+usb_scan_device(char *sys)
+{
+       struct cc_usbdev *usbdev;
+
+       usbdev = calloc(1, sizeof (struct cc_usbdev));
+       if (!usbdev)
+               return NULL;
+       usbdev->sys = strdup(sys);
+       usbdev->manufacturer = load_string(sys, "manufacturer");
+       usbdev->product = load_string(sys, "product");
+       usbdev->serial = load_string(sys, "serial");
+       usbdev->idProduct = load_hex(sys, "idProduct");
+       usbdev->idVendor = load_hex(sys, "idVendor");
+       usbdev->tty = usb_tty(sys);
+       return usbdev;
+}
+
+static void
+usbdev_free(struct cc_usbdev *usbdev)
+{
+       free(usbdev->sys);
+       free(usbdev->manufacturer);
+       free(usbdev->product);
+       free(usbdev->serial);
+       free(usbdev->tty);
+       free(usbdev);
+}
+
+#define USB_DEVICES    "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+       const char      *n = d->d_name;
+       char    c;
+
+       while ((c = *n++)) {
+               if (isdigit(c))
+                       continue;
+               if (c == '-')
+                       continue;
+               if (c == '.' && n != d->d_name + 1)
+                       continue;
+               return 0;
+       }
+       return 1;
+}
+
+struct cc_usbdevs *
+cc_usbdevs_scan(void)
+{
+       int                     e;
+       struct dirent           **ents;
+       char                    *dir;
+       struct cc_usbdev        *dev;
+       struct cc_usbdevs       *devs;
+       int                     n;
+
+       devs = calloc(1, sizeof (struct cc_usbdevs));
+       if (!devs)
+               return NULL;
+
+       n = scandir (USB_DEVICES, &ents,
+                    dir_filter_dev,
+                    alphasort);
+       if (!n)
+               return 0;
+       for (e = 0; e < n; e++) {
+               dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+               dev = usb_scan_device(dir);
+               free(dir);
+               if (dev->idVendor == 0xfffe && dev->tty) {
+                       if (devs->dev)
+                               devs->dev = realloc(devs->dev,
+                                                   devs->ndev + 1 * sizeof (struct usbdev *));
+                       else
+                               devs->dev = malloc (sizeof (struct usbdev *));
+                       devs->dev[devs->ndev++] = dev;
+               }
+       }
+       free(ents);
+       return devs;
+}
+
+void
+cc_usbdevs_free(struct cc_usbdevs *usbdevs)
+{
+       int     i;
+
+       if (!usbdevs)
+               return;
+       for (i = 0; i < usbdevs->ndev; i++)
+               usbdev_free(usbdevs->dev[i]);
+       free(usbdevs);
+}
diff --git a/ao-tools/lib/cc-util.c b/ao-tools/lib/cc-util.c
new file mode 100644 (file)
index 0000000..7104470
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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 "cc.h"
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+
+char *
+cc_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 *
+cc_basename(char *file)
+{
+       char *b;
+
+       b = strrchr(file, '/');
+       if (!b)
+               return file;
+       return b + 1;
+}
+
+int
+cc_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;
+}
diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h
new file mode 100644 (file)
index 0000000..dad11bf
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#ifndef _CC_H_
+#define _CC_H_
+
+char *
+cc_fullname (char *dir, char *file);
+
+char *
+cc_basename(char *file);
+
+int
+cc_mkdir(char *dir);
+
+struct cc_usbdev {
+       char    *sys;
+       char    *tty;
+       char    *manufacturer;
+       char    *product;
+       char    *serial;
+       int     idProduct;
+       int     idVendor;
+};
+
+struct cc_usbdevs {
+       struct cc_usbdev        **dev;
+       int                     ndev;
+};
+
+void
+cc_usbdevs_free(struct cc_usbdevs *usbdevs);
+
+struct cc_usbdevs *
+cc_usbdevs_scan(void);
+
+#endif /* _CC_H_ */
diff --git a/ao-view/.gitignore b/ao-view/.gitignore
deleted file mode 100644 (file)
index 24fbc59..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-*.o
-aoview
-aoview_glade.h
-aoview_flite
diff --git a/ao-view/Makefile.am b/ao-view/Makefile.am
deleted file mode 100644 (file)
index 17661c8..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-VERSION=$(shell git describe)
-
-AM_CFLAGS=$(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
-
-bin_PROGRAMS=ao-view
-
-ao_view_LDADD=$(GNOME_LIBS) $(FLITE_LIBS) $(ALSA_LIBS)
-
-ao_view_SOURCES = \
-       aoview_main.c \
-       aoview_dev.c \
-       aoview_dev_dialog.c \
-       aoview_serial.c \
-       aoview_monitor.c \
-       aoview_state.c \
-       aoview_convert.c \
-       aoview_log.c \
-       aoview_table.c \
-       aoview_util.c \
-       aoview_file.c \
-       aoview_eeprom.c \
-       aoview_voice.c \
-       aoview_replay.c \
-       aoview_label.c \
-       aoview_flite.c \
-       aoview.h
-
-BUILT_SOURCES = aoview_glade.h
-
-CLEANFILES = aoview_glade.h
-
-man_MANS=ao-view.1
-
-aoview_glade.h: aoview.glade
-       sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
diff --git a/ao-view/ao-view.1 b/ao-view/ao-view.1
deleted file mode 100644 (file)
index 99834c4..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-.\"
-.\" 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; either version 2 of the License, or
-.\" (at your option) any later version.
-.\"
-.\" 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.
-.\"
-.\"
-.TH AO-VIEW 1 "ao-view" ""
-.SH NAME
-ao-view \- Rocket flight monitor
-.SH SYNOPSIS
-.B "ao-view"
-[\--tty \fItty-device\fP]
-.SH DESCRIPTION
-.I ao-view
-connects to a TeleDongle or TeleMetrum device through a USB serial device.
-It provides a user interface to monitor, record and review rocket flight data.
-.SH OPTIONS
-The usual Gtk+ command line options can be used, along with
-.IP "\--tty"
-This selects a target device to connect at startup time to.
-The target device may also be selected through the user interface.
-.SH USAGE
-When connected to a TeleDongle device, ao-view turns on the radio
-receiver and listens for telemetry packets. It displays the received
-telemetry data, and reports flight status via voice synthesis. All
-received telemetry information is recorded to a file.
-.P
-When connected to a TeleMetrum device, ao-view downloads the eeprom
-data and stores it in a file.
-.SH FILES
-All data log files are recorded into a user-specified directory
-(default ~/AltOS). Files are named using the current date, the serial
-number of the reporting device, the flight number recorded in the data
-and either '.telem' for telemetry data or '.eeprom' for eeprom data.
-.SH "SEE ALSO"
-ao-load(1), ao-eeprom(1)
-.SH AUTHOR
-Keith Packard
diff --git a/ao-view/aoview.glade b/ao-view/aoview.glade
deleted file mode 100644 (file)
index 9a74611..0000000
+++ /dev/null
@@ -1,744 +0,0 @@
-<?xml version="1.0"?>
-<glade-interface>
-  <!-- interface-requires gtk+ 2.16 -->
-  <!-- interface-naming-policy project-wide -->
-  <widget class="GtkWindow" id="aoview">
-    <property name="width_request">900</property>
-    <property name="height_request">700</property>
-    <property name="visible">True</property>
-    <property name="title" translatable="yes">AltOS View</property>
-    <child>
-      <widget class="GtkVBox" id="vbox1">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <widget class="GtkMenuBar" id="menubar1">
-            <property name="visible">True</property>
-            <child>
-              <widget class="GtkMenuItem" id="menuitem1">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_File</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="menu1">
-                    <property name="visible">True</property>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem1">
-                        <property name="label">gtk-new</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem2">
-                        <property name="label">gtk-open</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem3">
-                        <property name="label">gtk-save</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem4">
-                        <property name="label">gtk-save-as</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem5">
-                        <property name="label">gtk-quit</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="gtk_main_quit"/>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="menuitem2">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Edit</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="menu2">
-                    <property name="visible">True</property>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem6">
-                        <property name="label">gtk-cut</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem7">
-                        <property name="label">gtk-copy</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem8">
-                        <property name="label">gtk-paste</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem9">
-                        <property name="label">gtk-delete</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="menuitem3">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Device</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="menu4">
-                    <property name="visible">True</property>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="ao_connect">
-                        <property name="label" translatable="yes">_Connect to device</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
-                        <signal name="activate" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image1">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-connect</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="ao_disconnect">
-                        <property name="label" translatable="yes">_Disconnect</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="image2">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-disconnect</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="seperator">
-                        <property name="visible">True</property>
-                        <property name="sensitive">False</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="ao_savelog">
-                        <property name="label" translatable="yes">_Save EEPROM data</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
-                        <signal name="activate" handler="gtk_widget_show" object="device_connect_dialog"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image5">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-save</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="ao_replay">
-                        <property name="label" translatable="yes">_Replay</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate_item" handler="gtk_widget_show" object="ao_replay_dialog" after="yes"/>
-                        <signal name="activate" handler="gtk_widget_show" object="ao_replay_dialog"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image6">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-media-play</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </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="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="file_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="file_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="menuitem6">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Voice</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="menu6">
-                    <property name="visible">True</property>
-                    <child>
-                      <widget class="GtkCheckMenuItem" id="voice_enable">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Enable _Voice</property>
-                        <property name="use_underline">True</property>
-                        <property name="active">True</property>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="menuitem4">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Help</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="menu3">
-                    <property name="visible">True</property>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="imagemenuitem10">
-                        <property name="label">gtk-about</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="gtk_widget_show" object="about_dialog" after="yes"/>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkTable" id="table1">
-            <property name="visible">True</property>
-            <property name="n_rows">2</property>
-            <property name="n_columns">4</property>
-            <property name="row_spacing">3</property>
-            <property name="homogeneous">True</property>
-            <child>
-              <widget class="GtkLabel" id="height_label">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Height (m)</property>
-                <property name="justify">center</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="state_label">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">State</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="rssi_label">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">RSSI (dBm)</property>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="height_value">
-                <property name="visible">True</property>
-                <property name="ypad">2</property>
-                <property name="label" translatable="yes">0</property>
-                <property name="selectable">True</property>
-              </widget>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="state_value">
-                <property name="visible">True</property>
-                <property name="ypad">2</property>
-                <property name="label" translatable="yes">pad</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="rssi_value">
-                <property name="visible">True</property>
-                <property name="ypad">2</property>
-                <property name="label" translatable="yes">-50</property>
-                <property name="selectable">True</property>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="speed_label">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Speed (m/s)</property>
-              </widget>
-              <packing>
-                <property name="left_attach">3</property>
-                <property name="right_attach">4</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="speed_value">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">0</property>
-                <property name="selectable">True</property>
-              </widget>
-              <packing>
-                <property name="left_attach">3</property>
-                <property name="right_attach">4</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkHBox" id="hbox1">
-            <property name="visible">True</property>
-            <child>
-              <widget class="GtkTreeView" id="dataview_0">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="show_expanders">False</property>
-                <property name="enable_grid_lines">both</property>
-              </widget>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkTreeView" id="dataview_1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="show_expanders">False</property>
-                <property name="enable_grid_lines">both</property>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkTreeView" id="dataview_2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="show_expanders">False</property>
-                <property name="enable_grid_lines">both</property>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">2</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-  <widget class="GtkDialog" id="device_connect_dialog">
-    <property name="border_width">5</property>
-    <property name="type_hint">normal</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child>
-          <widget class="GtkTreeView" id="dev_list">
-            <property name="width_request">300</property>
-            <property name="height_request">100</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="headers_clickable">False</property>
-            <property name="rules_hint">True</property>
-            <property name="search_column">0</property>
-            <property name="show_expanders">False</property>
-            <property name="level_indentation">1</property>
-            <property name="enable_grid_lines">both</property>
-            <property name="enable_tree_lines">True</property>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <widget class="GtkHButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <widget class="GtkButton" id="cancel_button">
-                <property name="label">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>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="connect_button">
-                <property name="label">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="file_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="file_configure_cancel">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-                <signal name="clicked" handler="gtk_widget_hide" object="file_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="file_configure_ok">
-                <property name="label">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>
-                <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="GtkMessageDialog" id="file_fail_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Failed to create log</property>
-    <property name="type_hint">normal</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="transient_for">aoview</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>
-  <widget class="GtkMessageDialog" id="dev_open_fail_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Failed to open device</property>
-    <property name="type_hint">normal</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="transient_for">aoview</property>
-    <property name="message_type">error</property>
-    <property name="buttons">close</property>
-    <property name="text">Cannot open device</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox6">
-        <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_area6">
-            <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>
-  <widget class="GtkAboutDialog" id="about_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">About AoView</property>
-    <property name="resizable">False</property>
-    <property name="type_hint">normal</property>
-    <property name="transient_for">aoview</property>
-    <property name="has_separator">False</property>
-    <property name="program_name">AoView</property>
-    <property name="copyright" translatable="yes">Copyright &#xA9; 2009 Keith Packard</property>
-    <property name="comments" translatable="yes">AltOS data capture and display.</property>
-    <property name="website">http://altusmetrum.org</property>
-    <property name="license" translatable="yes">AoView 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.
-
-AoView 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 AoView; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</property>
-    <property name="authors">Keith Packard &lt;keithp@keithp.com&gt;</property>
-    <property name="wrap_license">True</property>
-    <signal name="close" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
-    <signal name="response" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox7">
-        <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_area7">
-            <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>
-  <widget class="GtkMessageDialog" id="ao_save_done">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">EEPROM save complete</property>
-    <property name="type_hint">normal</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="transient_for">aoview</property>
-    <property name="buttons">close</property>
-    <property name="text">Saving EEPROM data as</property>
-    <property name="secondary_text">&lt;filename&gt;</property>
-    <signal name="close" handler="gtk_widget_hide" object="ao_save_done"/>
-    <signal name="response" handler="gtk_widget_hide" object="ao_save_done"/>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox11">
-        <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_area11">
-            <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>
-  <widget class="GtkFileChooserDialog" id="ao_replay_dialog">
-    <property name="border_width">5</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="type_hint">dialog</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="transient_for">aoview</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox10">
-        <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_area10">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <widget class="GtkButton" id="ao_replay_cancel">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-                <signal name="clicked" handler="gtk_widget_hide" object="ao_replay_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="ao_replay_ok">
-                <property name="label">gtk-ok</property>
-                <property name="visible">True</property>
-                <property name="can_focus">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>
-</glade-interface>
diff --git a/ao-view/aoview.h b/ao-view/aoview.h
deleted file mode 100644 (file)
index 9ca6529..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _AOVIEW_H_
-#define _AOVIEW_H_
-
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <assert.h>
-#include <math.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <gconf/gconf-client.h>
-
-struct usbdev {
-       char    *sys;
-       char    *tty;
-       char    *manufacturer;
-       char    *product;
-       char    *serial;
-       int     idProduct;
-       int     idVendor;
-};
-
-struct aogps_time {
-       int hour;
-       int minute;
-       int second;
-};
-
-struct aogps {
-       int     nsat;
-       int     gps_locked;
-       int     gps_connected;
-       struct aogps_time gps_time;
-       double  lat;            /* degrees (+N -S) */
-       double  lon;            /* degrees (+E -W) */
-       int     alt;            /* m */
-
-       int     gps_extended;   /* has extra data */
-       double  ground_speed;   /* m/s */
-       int     course;         /* degrees */
-       double  climb_rate;     /* m/s */
-       double  hdop;           /* unitless? */
-       int     h_error;        /* m */
-       int     v_error;        /* m */
-};
-
-#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
-#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
-#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
-#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
-#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
-#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
-#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
-#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
-
-struct aogps_sat {
-       int     svid;
-       int     state;
-       int     c_n0;
-};
-
-struct aogps_tracking {
-       int                     channels;
-       struct aogps_sat        sats[12];
-};
-
-struct aodata {
-       char    callsign[16];
-       int     serial;
-       int     rssi;
-       char    state[16];
-       int     tick;
-       int     accel;
-       int     pres;
-       int     temp;
-       int     batt;
-       int     drogue;
-       int     main;
-       int     flight_accel;
-       int     ground_accel;
-       int     flight_vel;
-       int     flight_pres;
-       int     ground_pres;
-       struct aogps    gps;
-       struct aogps_tracking   gps_tracking;
-};
-
-struct aostate {
-       struct aodata   data;
-
-       /* derived data */
-
-       struct aodata   prev_data;
-
-       double          report_time;
-
-       gboolean        ascent; /* going up? */
-
-       int     ground_altitude;
-       int     height;
-       double  speed;
-       double  acceleration;
-       double  battery;
-       double  temperature;
-       double  main_sense;
-       double  drogue_sense;
-       double  baro_speed;
-
-       int     max_height;
-       double  max_acceleration;
-       double  max_speed;
-
-       struct aogps    gps;
-       struct aogps_tracking   gps_tracking;
-
-       int     gps_valid;
-       double  pad_lat;
-       double  pad_lon;
-       double  pad_alt;
-       double  pad_lat_total;
-       double  pad_lon_total;
-       double  pad_alt_total;
-       int     npad;
-       int     prev_npad;
-
-       double  distance;
-       double  bearing;
-       int     gps_height;
-
-       int     speak_tick;
-       int     speak_altitude;
-};
-
-extern struct aostate aostate;
-
-/* GPS is 'stable' when we've seen at least this many samples */
-#define MIN_PAD_SAMPLES        10
-
-void
-aoview_monitor_disconnect(void);
-
-gboolean
-aoview_monitor_connect(char *tty);
-
-gboolean
-aoview_monitor_parse(const char *line);
-
-void
-aoview_monitor_reset(void);
-
-struct aoview_serial *
-aoview_serial_open(const char *tty);
-
-void
-aoview_serial_close(struct aoview_serial *serial);
-
-typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents);
-
-void
-aoview_serial_set_callback(struct aoview_serial *serial,
-                          aoview_serial_callback func);
-
-void
-aoview_serial_printf(struct aoview_serial *serial, char *format, ...);
-
-int
-aoview_serial_read(struct aoview_serial *serial, char *buf, int len);
-
-int
-aoview_serial_getc(struct aoview_serial *serial);
-
-void
-aoview_dev_dialog_init(GladeXML *xml);
-
-int
-aoview_usb_scan(struct usbdev ***devs_ret);
-
-void
-aoview_usbdev_free(struct usbdev *usbdev);
-
-void
-aoview_state_notify(struct aodata *data);
-
-void
-aoview_state_new(void);
-
-void
-aoview_state_init(GladeXML *xml);
-
-int16_t
-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_log_new(void);
-
-void
-aoview_table_start(void);
-
-void
-aoview_table_add_row(int column, char *label, char *format, ...);
-
-void
-aoview_table_finish(void);
-
-void
-aoview_table_init(GladeXML *xml);
-
-void
-aoview_table_clear(void);
-
-struct aoview_file;
-
-extern char *aoview_file_dir;
-
-void
-aoview_file_finish(struct aoview_file *file);
-
-gboolean
-aoview_file_start(struct aoview_file *file);
-
-const char *
-aoview_file_name(struct aoview_file *file);
-
-void
-aoview_file_set_serial(struct aoview_file *file, int serial);
-
-int
-aoview_file_get_serial(struct aoview_file *file);
-
-void
-aoview_file_printf(struct aoview_file *file, char *format, ...);
-
-void
-aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap);
-
-struct aoview_file *
-aoview_file_new(char *ext);
-
-void
-aoview_file_destroy(struct aoview_file *file);
-
-void
-aoview_file_init(GladeXML *xml);
-
-/* aoview_eeprom.c */
-
-gboolean
-aoview_eeprom_save(const char *device);
-
-void
-aoview_eeprom_init(GladeXML *xml);
-
-/* aoview_voice.c */
-void aoview_voice_open(void);
-
-void aoview_voice_close(void);
-
-void aoview_voice_speak(char *format, ...);
-
-/* aoview_label.c */
-
-void aoview_label_init(GladeXML *xml);
-
-void
-aoview_label_show(struct aostate *state);
-
-/* aoview_flite.c */
-
-FILE *
-aoview_flite_start(void);
-
-void
-aoview_flite_stop(void);
-
-/* aoview_main.c */
-
-extern char *aoview_tty;
-
-#endif /* _AOVIEW_H_ */
diff --git a/ao-view/aoview_convert.c b/ao-view/aoview_convert.c
deleted file mode 100644 (file)
index 0241664..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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 int16_t altitude_table[2048] = {
-#include "altitude.h"
-};
-
-int16_t
-aoview_pres_to_altitude(int16_t pres)
-{
-       pres = pres >> 4;
-       if (pres < 0) pres = 0;
-       if (pres > 2047) pres = 2047;
-       return altitude_table[pres];
-}
-
-int16_t
-aoview_altitude_to_pres(int16_t alt)
-{
-       int16_t pres;
-
-       for (pres = 0; pres < 2047; pres++)
-               if (altitude_table[pres] <= alt)
-                       break;
-       return pres << 4;
-}
diff --git a/ao-view/aoview_dev.c b/ao-view/aoview_dev.c
deleted file mode 100644 (file)
index 9b8cc19..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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"
-#include <ctype.h>
-#include <dirent.h>
-
-static char *
-load_string(char *dir, char *file)
-{
-       char    *full = aoview_fullname(dir, file);
-       char    line[4096];
-       char    *r;
-       FILE    *f;
-       int     rlen;
-
-       f = fopen(full, "r");
-       free(full);
-       if (!f)
-               return NULL;
-       r = fgets(line, sizeof (line), f);
-       fclose(f);
-       if (!r)
-               return NULL;
-       rlen = strlen(r);
-       if (r[rlen-1] == '\n')
-               r[rlen-1] = '\0';
-       return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
-       char    *line;
-       char    *end;
-       long    i;
-
-       line = load_string(dir, file);
-       if (!line)
-               return -1;
-       i = strtol(line, &end, 16);
-       free(line);
-       if (end == line)
-               return -1;
-       return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-static char *
-usb_tty(char *sys)
-{
-       char *base;
-       int num_configs;
-       int config;
-       struct dirent **namelist;
-       int interface;
-       int num_interfaces;
-       char endpoint_base[20];
-       char *endpoint_full;
-       char *tty_dir;
-       int ntty;
-       char *tty;
-
-       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 = aoview_fullname(sys, endpoint_base);
-
-                       /* Check for tty:ttyACMx style names
-                        */
-                       ntty = scandir(endpoint_full, &namelist,
-                                      dir_filter_tty_colon,
-                                      alphasort);
-                       if (ntty > 0) {
-                               free(endpoint_full);
-                               tty = aoview_fullname("/dev", namelist[0]->d_name + 4);
-                               free(namelist);
-                               return tty;
-                       }
-
-                       /* Check for tty/ttyACMx style names
-                        */
-                       tty_dir = aoview_fullname(endpoint_full, "tty");
-                       free(endpoint_full);
-                       ntty = scandir(tty_dir, &namelist,
-                                      dir_filter_tty,
-                                      alphasort);
-                       free (tty_dir);
-                       if (ntty > 0) {
-                               tty = aoview_fullname("/dev", namelist[0]->d_name);
-                               free(namelist);
-                               return tty;
-                       }
-               }
-       }
-       return NULL;
-}
-
-static struct usbdev *
-usb_scan_device(char *sys)
-{
-       struct usbdev *usbdev;
-
-       usbdev = calloc(1, sizeof (struct usbdev));
-       if (!usbdev)
-               return NULL;
-       usbdev->sys = strdup(sys);
-       usbdev->manufacturer = load_string(sys, "manufacturer");
-       usbdev->product = load_string(sys, "product");
-       usbdev->serial = load_string(sys, "serial");
-       usbdev->idProduct = load_hex(sys, "idProduct");
-       usbdev->idVendor = load_hex(sys, "idVendor");
-       usbdev->tty = usb_tty(sys);
-       return usbdev;
-}
-
-void
-aoview_usbdev_free(struct usbdev *usbdev)
-{
-       free(usbdev->sys);
-       free(usbdev->manufacturer);
-       free(usbdev->product);
-       free(usbdev->serial);
-       free(usbdev->tty);
-       free(usbdev);
-}
-
-#define USB_DEVICES    "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
-       const char      *n = d->d_name;
-       char    c;
-
-       while ((c = *n++)) {
-               if (isdigit(c))
-                       continue;
-               if (c == '-')
-                       continue;
-               if (c == '.' && n != d->d_name + 1)
-                       continue;
-               return 0;
-       }
-       return 1;
-}
-
-int
-aoview_usb_scan(struct usbdev ***devs_ret)
-{
-       int             n;
-       int             ndev = 0;
-       int             e;
-       struct dirent   **ents;
-       char            *dir;
-       struct usbdev   **devs = NULL;
-       struct usbdev   *dev;
-
-       n = scandir (USB_DEVICES, &ents,
-                    dir_filter_dev,
-                    alphasort);
-       if (!n)
-               return 0;
-       for (e = 0; e < n; e++) {
-               dir = aoview_fullname(USB_DEVICES, ents[e]->d_name);
-               dev = usb_scan_device(dir);
-               free(dir);
-               if (dev->idVendor == 0xfffe && dev->tty) {
-                       if (devs)
-                               devs = realloc(devs, ndev + 1 * sizeof (struct usbdev *));
-                       else
-                               devs = malloc (sizeof (struct usbdev *));
-                       devs[ndev++] = dev;
-               }
-       }
-       free(ents);
-       *devs_ret = devs;
-       return ndev;
-}
diff --git a/ao-view/aoview_dev_dialog.c b/ao-view/aoview_dev_dialog.c
deleted file mode 100644 (file)
index 3f92085..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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 void
-aoview_dev_dialog_map(GtkWidget *widget, gpointer data)
-{
-       GtkTreeView     *dev_list = data;
-       GtkListStore    *list_store;
-       GtkTreeIter     iter;
-       int             ndev, n;
-       struct usbdev   **devs;
-
-       list_store = gtk_list_store_new(3,
-                                       G_TYPE_STRING,
-                                       G_TYPE_STRING,
-                                       G_TYPE_STRING);
-
-       ndev = aoview_usb_scan(&devs);
-       for (n = 0; n < ndev; n++) {
-               gtk_list_store_append(list_store, &iter);
-               gtk_list_store_set(list_store, &iter,
-                                  0, devs[n]->product,
-                                  1, devs[n]->serial,
-                                  2, devs[n]->tty,
-                                  -1);
-       }
-       gtk_tree_view_set_model (dev_list, GTK_TREE_MODEL(list_store));
-       g_object_unref(G_OBJECT(list_store));
-       gtk_tree_view_columns_autosize(dev_list);
-}
-
-static GtkMessageDialog *dev_open_fail_dialog;
-
-static void
-aoview_dev_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(dev_open_fail_dialog,
-                                                "\"%s\"", utf8_file);
-       if (utf8_file != name)
-               g_free(utf8_file);
-       gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog));
-       gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog));
-}
-
-gboolean       dialog_save_log;
-
-static void
-aoview_dev_selected(GtkTreeModel *model,
-                   GtkTreePath *path,
-                   GtkTreeIter *iter,
-                   gpointer data)
-{
-       gchar *string;
-       gtk_tree_model_get(model, iter,
-                          2, &string,
-                          -1);
-       if (dialog_save_log) {
-               dialog_save_log = FALSE;
-               if (!aoview_eeprom_save(string))
-                       aoview_dev_open_failed(string);
-       } else {
-               if (!aoview_monitor_connect(string))
-                       aoview_dev_open_failed(string);
-       }
-}
-
-static GtkWidget       *dialog;
-
-static void
-aoview_dev_dialog_connect(GtkWidget *widget, gpointer data)
-{
-       GtkTreeView             *dev_list = data;
-       GtkListStore            *list_store;
-       GtkTreeSelection        *tree_selection;
-
-       list_store = GTK_LIST_STORE(gtk_tree_view_get_model(dev_list));
-       tree_selection = gtk_tree_view_get_selection(dev_list);
-       gtk_tree_selection_selected_foreach(tree_selection,
-                                           aoview_dev_selected,
-                                           data);
-       gtk_widget_hide(dialog);
-}
-
-static void
-aoview_dev_disconnect(GtkWidget *widget)
-{
-       aoview_monitor_disconnect();
-}
-
-static void
-aoview_dev_savelog(GtkWidget *widget, gpointer data)
-{
-       dialog_save_log = TRUE;
-       gtk_widget_show(dialog);
-}
-
-#define _(a) a
-
-void
-aoview_dev_dialog_init(GladeXML *xml)
-{
-       GtkTreeView     *dev_list;
-       GtkWidget       *connect_button;
-       GtkTreeSelection        *dev_selection;
-       GtkWidget       *ao_disconnect;
-       GtkWidget       *ao_savelog;
-
-       dialog = glade_xml_get_widget(xml, "device_connect_dialog");
-       assert(dialog);
-
-       dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list"));
-       assert(dev_list);
-
-       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);
-
-       g_signal_connect(G_OBJECT(dialog), "map",
-                        G_CALLBACK(aoview_dev_dialog_map),
-                        dev_list);
-
-       connect_button = glade_xml_get_widget(xml, "connect_button");
-       assert(connect_button);
-
-       g_signal_connect(G_OBJECT(connect_button), "clicked",
-                        G_CALLBACK(aoview_dev_dialog_connect),
-                        dev_list);
-
-
-       ao_disconnect = glade_xml_get_widget(xml, "ao_disconnect");
-       assert(ao_disconnect);
-
-       g_signal_connect(G_OBJECT(ao_disconnect), "activate",
-                        G_CALLBACK(aoview_dev_disconnect),
-                        ao_disconnect);
-
-       ao_savelog = glade_xml_get_widget(xml, "ao_savelog");
-       assert(ao_savelog);
-
-       g_signal_connect(G_OBJECT(ao_savelog), "activate",
-                        G_CALLBACK(aoview_dev_savelog),
-                        dialog);
-       dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog"));
-       assert(dev_open_fail_dialog);
-}
diff --git a/ao-view/aoview_eeprom.c b/ao-view/aoview_eeprom.c
deleted file mode 100644 (file)
index 34e2dee..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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 EEPROM_LEN     1024
-
-static struct aoview_file      *eeprom_file;
-static char                    eeprom_line[EEPROM_LEN + 1];
-static int                     eeprom_pos;
-static GtkMessageDialog                *eeprom_save_done;
-static GtkWidget               *eeprom_save_close;
-static gboolean                        eeprom_save_shown;
-
-static void
-aoview_eeprom_disconnect(struct aoview_serial *serial)
-{
-       aoview_file_finish(eeprom_file);
-}
-
-static void
-aoview_eeprom_done(struct aoview_serial *serial)
-{
-       gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
-                            "EEPROM data saved");
-       gtk_message_dialog_set_markup(eeprom_save_done,
-                                     "<b>EEPROM data saved as</b>");
-       if (!eeprom_save_shown)
-               gtk_widget_show(GTK_WIDGET(eeprom_save_done));
-       eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
-       if (eeprom_save_close)
-               gtk_widget_set_sensitive(eeprom_save_close, TRUE);
-       aoview_eeprom_disconnect(serial);
-}
-
-static gboolean
-aoview_eeprom_parse(struct aoview_serial *serial,
-                   char *line)
-{
-       char            cmd;
-       int             tick;
-       int             a;
-       int             b;
-       int             serial_number;
-       const char      *name;
-       char            *utf8_name;
-
-       if (!strcmp(line, "end")) {
-               aoview_eeprom_done(serial);
-               return FALSE;
-       }
-       if (sscanf(line, "serial-number %u", &serial_number) == 1) {
-               aoview_file_set_serial(eeprom_file, serial_number);
-       } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) {
-               aoview_file_printf(eeprom_file, "%s\n", line);
-               if (cmd == 'S' && a == 8) {
-                       aoview_eeprom_done(serial);
-                       return FALSE;
-               }
-
-               if (!eeprom_save_shown)
-               {
-                       name = aoview_file_name(eeprom_file);
-                       if (name) {
-                               utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
-                               if (!utf8_name)
-                                       utf8_name = (char *) name;
-                               gtk_widget_set_sensitive(eeprom_save_close, FALSE);
-                               gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
-                                                    "Saving EEPROM data");
-                               gtk_message_dialog_set_markup(eeprom_save_done,
-                                                             "<b>Saving EEPROM data as</b>");
-                               gtk_message_dialog_format_secondary_text(eeprom_save_done, "%s",
-                                                                        utf8_name);
-                               if (utf8_name != name)
-                                       g_free(utf8_name);
-                               gtk_container_check_resize(GTK_CONTAINER(eeprom_save_done));
-                               gtk_widget_show(GTK_WIDGET(eeprom_save_done));
-                               eeprom_save_shown = TRUE;
-                               eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
-                               if (eeprom_save_close)
-                                       gtk_widget_set_sensitive(eeprom_save_close, FALSE);
-                       }
-               }
-       }
-       return TRUE;
-}
-
-static void
-aoview_eeprom_callback(gpointer user_data,
-                      struct aoview_serial *serial,
-                      gint revents)
-{
-       int     c;
-
-       if (revents & (G_IO_HUP|G_IO_ERR)) {
-               aoview_eeprom_disconnect(serial);
-               return;
-       }
-       if (revents & G_IO_IN) {
-               for (;;) {
-                       c = aoview_serial_getc(serial);
-                       if (c == -1)
-                               break;
-                       if (c == '\r')
-                               continue;
-                       if (c == '\n') {
-                               eeprom_line[eeprom_pos] = '\0';
-                               if (eeprom_pos)
-                               if (!aoview_eeprom_parse(serial, eeprom_line))
-                                       break;
-                               eeprom_pos = 0;
-                       } else if (eeprom_pos < EEPROM_LEN)
-                               eeprom_line[eeprom_pos++] = c;
-               }
-       }
-}
-
-gboolean
-aoview_eeprom_save(const char *device)
-{
-       struct aoview_serial    *serial;
-
-       gtk_widget_hide(GTK_WIDGET(eeprom_save_done));
-       eeprom_save_shown = FALSE;
-       serial = aoview_serial_open(device);
-       if (!serial)
-               return FALSE;
-       aoview_serial_set_callback(serial, aoview_eeprom_callback);
-       aoview_serial_printf(serial, "v\nl\n");
-       return TRUE;
-}
-
-void
-aoview_eeprom_init(GladeXML *xml)
-{
-       eeprom_file = aoview_file_new("eeprom");
-       assert(eeprom_file);
-
-       eeprom_save_done = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "ao_save_done"));
-       assert(eeprom_save_done);
-
-}
diff --git a/ao-view/aoview_file.c b/ao-view/aoview_file.c
deleted file mode 100644 (file)
index 5288c2f..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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_file_dir;
-
-#define ALTOS_DIR_PATH "/apps/aoview/log_dir"
-#define DEFAULT_DIR    "AltOS"
-
-struct aoview_file {
-       char    *ext;
-       FILE    *file;
-       char    *name;
-       int     failed;
-       int     serial;
-       int     sequence;
-};
-
-static void
-aoview_file_save_conf(void)
-{
-       GConfClient     *gconf_client;
-
-       gconf_client = gconf_client_get_default();
-       if (gconf_client)
-       {
-               gconf_client_set_string(gconf_client,
-                                       ALTOS_DIR_PATH,
-                                       aoview_file_dir,
-                                       NULL);
-               g_object_unref(G_OBJECT(gconf_client));
-       }
-}
-
-static void
-aoview_file_configure(GtkWidget *widget, gpointer data)
-{
-       GtkFileChooser *chooser = data;
-       aoview_file_dir = gtk_file_chooser_get_filename(chooser);
-       aoview_file_save_conf();
-       gtk_widget_hide(GTK_WIDGET(chooser));
-}
-
-void
-aoview_file_finish(struct aoview_file *file)
-{
-       if (file->file) {
-               fclose(file->file);
-               file->file = NULL;
-               free(file->name);
-               file->name = NULL;
-       }
-       file->failed = 0;
-}
-
-const char *
-aoview_file_name(struct aoview_file *file)
-{
-       return file->name;
-}
-
-static GtkMessageDialog *file_fail_dialog;
-
-static void
-aoview_file_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(file_fail_dialog,
-                                                "\"%s\"", utf8_file);
-       if (utf8_file != name)
-               g_free(utf8_file);
-       gtk_widget_show(GTK_WIDGET(file_fail_dialog));
-}
-
-gboolean
-aoview_file_start(struct aoview_file *file)
-{
-       char            base[50];
-       struct tm       tm;
-       time_t          now;
-       char            *full;
-       int             r;
-
-       if (file->file)
-               return TRUE;
-
-       if (file->failed)
-               return FALSE;
-
-       now = time(NULL);
-       (void) localtime_r(&now, &tm);
-       aoview_mkdir(aoview_file_dir);
-       for (;;) {
-               snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
-                       tm.tm_year + 1900,
-                       tm.tm_mon + 1,
-                       tm.tm_mday,
-                       file->serial,
-                       file->sequence,
-                       file->ext);
-               full = aoview_fullname(aoview_file_dir, base);
-               r = access(full, F_OK);
-               if (r < 0) {
-                       file->file = fopen(full, "w");
-                       if (!file->file) {
-                               aoview_file_open_failed(full);
-                               free(full);
-                               file->failed = 1;
-                               return FALSE;
-                       } else {
-                               setlinebuf(file->file);
-                               file->name = full;
-                               return TRUE;
-                       }
-               }
-               free(full);
-               file->sequence++;
-       }
-}
-
-void
-aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap)
-{
-       if (!aoview_file_start(file))
-               return;
-       vfprintf(file->file, format, ap);
-}
-
-void
-aoview_file_printf(struct aoview_file *file, char *format, ...)
-{
-       va_list ap;
-
-       va_start(ap, format);
-       aoview_file_vprintf(file, format, ap);
-       va_end(ap);
-}
-
-struct aoview_file *
-aoview_file_new(char *ext)
-{
-       struct aoview_file      *file;
-
-       file = calloc (1, sizeof (struct aoview_file));
-       if (!file)
-               return NULL;
-       file->ext = strdup(ext);
-       if (!file->ext) {
-               free(file);
-               return NULL;
-       }
-       return file;
-}
-
-void
-aoview_file_destroy(struct aoview_file *file)
-{
-       if (file->file)
-               fclose(file->file);
-       if (file->name)
-               free(file->name);
-       free(file->ext);
-       free(file);
-}
-
-void
-aoview_file_set_serial(struct aoview_file *file, int serial)
-{
-       if (serial != file->serial)
-               aoview_file_finish(file);
-       file->serial = serial;
-}
-
-int
-aoview_file_get_serial(struct aoview_file *file)
-{
-       return file->serial;
-}
-
-void
-aoview_file_init(GladeXML *xml)
-{
-       GConfClient     *gconf_client;
-       char            *file_dir = NULL;
-       GtkFileChooser  *file_chooser_dialog;
-       GtkWidget       *file_configure_ok;
-
-       g_type_init();
-       gconf_client = gconf_client_get_default();
-       if (gconf_client)
-       {
-               file_dir = gconf_client_get_string(gconf_client,
-                                                  ALTOS_DIR_PATH,
-                                                  NULL);
-               g_object_unref(G_OBJECT(gconf_client));
-       }
-       if (!file_dir) {
-               aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR);
-               aoview_file_save_conf();
-       } else {
-               aoview_file_dir = strdup(file_dir);
-       }
-
-       file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog"));
-       assert(file_chooser_dialog);
-       gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir);
-
-       file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok");
-       assert(file_configure_ok);
-
-       g_signal_connect(G_OBJECT(file_configure_ok), "clicked",
-                        G_CALLBACK(aoview_file_configure),
-                        file_chooser_dialog);
-
-
-       file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog"));
-       assert(file_fail_dialog);
-}
diff --git a/ao-view/aoview_flite.c b/ao-view/aoview_flite.c
deleted file mode 100644 (file)
index e1b7589..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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 <stdio.h>
-#include <flite/flite.h>
-#include "aoview.h"
-#include <alsa/asoundlib.h>
-
-cst_voice *register_cmu_us_kal();
-static cst_voice *voice;
-
-static FILE *pipe_write;
-static GThread *aoview_flite_thread;
-
-static snd_pcm_t       *alsa_handle;
-
-gpointer
-aoview_flite_task(gpointer data)
-{
-       FILE            *input = data;
-       char            line[1024];
-       cst_wave        *wave;
-       int             rate;
-       int             channels;
-       int             err;
-       char            *samples;
-       int             num_samples;
-
-       err = snd_pcm_open(&alsa_handle, "default",
-                          SND_PCM_STREAM_PLAYBACK, 0);
-       if (err >= 0)
-       {
-               if (err < 0) {
-                       snd_pcm_close(alsa_handle);
-                       alsa_handle = 0;
-               }
-       }
-       rate = 0;
-       channels = 0;
-       while (fgets(line, sizeof (line) - 1, input) != NULL) {
-               if (!alsa_handle)
-                       continue;
-               wave = flite_text_to_wave(line, voice);
-               if (wave->sample_rate != rate ||
-                   wave->num_channels != channels)
-               {
-                       rate = wave->sample_rate;
-                       channels = wave->num_channels;
-                       err = snd_pcm_set_params(alsa_handle,
-                                                SND_PCM_FORMAT_S16,
-                                                SND_PCM_ACCESS_RW_INTERLEAVED,
-                                                channels,
-                                                rate,
-                                                1,
-                                                100000);
-                       if (err < 0)
-                               fprintf(stderr, "alsa set_params error %s\n",
-                                       strerror(-err));
-               }
-               err = snd_pcm_prepare(alsa_handle);
-               if (err < 0)
-                       fprintf(stderr, "alsa pcm_prepare error %s\n",
-                               strerror(-err));
-               samples = (char *) wave->samples;
-               num_samples = wave->num_samples;
-               while (num_samples > 0) {
-                       err = snd_pcm_writei(alsa_handle,
-                                            samples, num_samples);
-                       if (err <= 0) {
-                               fprintf(stderr, "alsa write error %s\n",
-                                       strerror(-err));
-                               break;
-                       }
-                       num_samples -= err;
-                       samples += err * 2 * channels;
-               }
-               snd_pcm_drain(alsa_handle);
-               delete_wave(wave);
-       }
-       snd_pcm_close(alsa_handle);
-       alsa_handle = 0;
-       return NULL;
-}
-
-void
-aoview_flite_stop(void)
-{
-       int status;
-       if (pipe_write) {
-               fclose(pipe_write);
-               pipe_write = NULL;
-       }
-       if (aoview_flite_thread) {
-               g_thread_join(aoview_flite_thread);
-               aoview_flite_thread = NULL;
-       }
-}
-
-FILE *
-aoview_flite_start(void)
-{
-       static once;
-       int     p[2];
-       GError  *error;
-       FILE    *pipe_read;
-
-       if (!once) {
-               flite_init();
-               voice = register_cmu_us_kal();
-               if (!voice) {
-                       perror("register voice");
-                       exit(1);
-               }
-       }
-       aoview_flite_stop();
-       pipe(p);
-       pipe_read = fdopen(p[0], "r");
-       pipe_write = fdopen(p[1], "w");
-       g_thread_create(aoview_flite_task, pipe_read, TRUE, &error);
-       return pipe_write;
-}
diff --git a/ao-view/aoview_label.c b/ao-view/aoview_label.c
deleted file mode 100644 (file)
index 2431362..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 struct {
-       char            *name;
-       char            *initial_value;
-       GtkLabel        *widget;
-} label_widgets[] = {
-       { "height_label", "Height (m)", NULL },
-       { "state_label", "State", NULL },
-       { "rssi_label", "RSSI (dBm)", NULL },
-       { "speed_label", "Speed (m/s)", NULL },
-       { "height_value", "0", NULL },
-       { "state_value", "pad", NULL },
-       { "rssi_value", "-50", NULL },
-       { "speed_value", "0", NULL },
-};
-
-static void
-aoview_label_assign(GtkLabel *widget, char *value)
-{
-       char    *markup;
-
-       markup = g_markup_printf_escaped("<span font_weight=\"bold\" size=\"xx-large\">%s</span>", value);
-       gtk_label_set_markup(widget, markup);
-       g_free(markup);
-}
-
-void
-aoview_label_show(struct aostate *state)
-{
-       char    line[1024];
-       sprintf(line, "%d", state->height);
-       aoview_label_assign(label_widgets[4].widget, line);
-
-       aoview_label_assign(label_widgets[5].widget, state->data.state);
-
-       sprintf(line, "%d", state->data.rssi);
-       aoview_label_assign(label_widgets[6].widget, line);
-
-       if (state->ascent)
-               sprintf(line, "%6.0f", fabs(state->speed));
-       else
-               sprintf(line, "%6.0f", fabs(state->baro_speed));
-       aoview_label_assign(label_widgets[7].widget, line);
-}
-
-void
-aoview_label_init(GladeXML *xml)
-{
-       int i;
-       for (i = 0; i < sizeof(label_widgets)/sizeof(label_widgets[0]); i++) {
-               label_widgets[i].widget = GTK_LABEL(glade_xml_get_widget(xml, label_widgets[i].name));
-               aoview_label_assign(label_widgets[i].widget, label_widgets[i].initial_value);
-               assert(label_widgets[i].widget);
-       }
-}
diff --git a/ao-view/aoview_log.c b/ao-view/aoview_log.c
deleted file mode 100644 (file)
index 1b89c28..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 struct aoview_file      *aoview_log;
-
-void
-aoview_log_new(void)
-{
-       aoview_file_finish(aoview_log);
-       aoview_state_new();
-}
-
-void
-aoview_log_set_serial(int serial)
-{
-       aoview_file_set_serial(aoview_log, serial);
-}
-
-int
-aoview_log_get_serial(void)
-{
-       return aoview_file_get_serial(aoview_log);
-}
-
-void
-aoview_log_printf(char *format, ...)
-{
-       va_list ap;
-
-       va_start(ap, format);
-       aoview_file_vprintf(aoview_log, format, ap);
-       va_end(ap);
-}
-
-static void
-aoview_log_new_item(GtkWidget *widget, gpointer data)
-{
-       aoview_file_finish(aoview_log);
-}
-
-void
-aoview_log_init(GladeXML *xml)
-{
-       GtkWidget       *log_new;
-
-       aoview_log = aoview_file_new("telem");
-       assert(aoview_log);
-
-       log_new = glade_xml_get_widget(xml, "log_new");
-       assert(log_new);
-       g_signal_connect(G_OBJECT(log_new), "activate",
-                        G_CALLBACK(aoview_log_new_item),
-                        NULL);
-}
diff --git a/ao-view/aoview_main.c b/ao-view/aoview_main.c
deleted file mode 100644 (file)
index 64c1c02..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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 const char aoview_glade[] = {
-#include "aoview_glade.h"
-};
-
-static void usage(void) {
-       printf("aoview [--device|-d device_file]");
-       exit(1);
-}
-
-static void destroy_event(GtkWidget *widget, gpointer data)
-{
-       gtk_main_quit();
-}
-
-extern int _Xdebug;
-char *aoview_tty = NULL;
-
-int main(int argc, char **argv)
-{
-       GladeXML *xml = NULL;
-       GtkWidget *mainwindow;
-       GtkAboutDialog *about_dialog;
-
-       static struct option long_options[] = {
-               { "tty", 1, 0, 'T'},
-               { "sync", 0, 0, 's'},
-               { 0, 0, 0, 0 }
-       };
-       for (;;) {
-               int c, temp;
-
-               c = getopt_long_only(argc, argv, "sT:", long_options, &temp);
-               if (c == -1)
-                       break;
-
-               switch (c) {
-               case 'T':
-                       aoview_tty = optarg;
-                       break;
-               case 's':
-                       _Xdebug = 1;
-                       break;
-               default:
-                       usage();
-               }
-       }
-
-       g_thread_init(NULL);
-       gtk_init(&argc, &argv);
-       glade_init();
-
-       xml = glade_xml_new_from_buffer(aoview_glade, sizeof (aoview_glade), NULL, NULL);
-
-       /* connect the signals in the interface */
-       glade_xml_signal_autoconnect(xml);
-
-       /* Hook up the close button. */
-       mainwindow = glade_xml_get_widget(xml, "aoview");
-       assert(mainwindow);
-
-       g_signal_connect (G_OBJECT(mainwindow), "destroy",
-           G_CALLBACK(destroy_event), NULL);
-
-       about_dialog = GTK_ABOUT_DIALOG(glade_xml_get_widget(xml, "about_dialog"));
-       assert(about_dialog);
-       gtk_about_dialog_set_version(about_dialog, AOVIEW_VERSION);
-
-       aoview_voice_init(xml);
-
-       aoview_dev_dialog_init(xml);
-
-       aoview_state_init(xml);
-
-       aoview_file_init(xml);
-
-       aoview_log_init(xml);
-
-       aoview_table_init(xml);
-
-       aoview_eeprom_init(xml);
-
-       aoview_replay_init(xml);
-
-       aoview_label_init(xml);
-
-       if (aoview_tty) {
-               if (!aoview_monitor_connect(aoview_tty)) {
-                       perror(aoview_tty);
-                       exit(1);
-               }
-       }
-       aoview_voice_speak("rocket flight monitor ready\n");
-
-       gtk_main();
-
-       return 0;
-}
diff --git a/ao-view/aoview_monitor.c b/ao-view/aoview_monitor.c
deleted file mode 100644 (file)
index 8564014..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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 struct aoview_serial *monitor_serial;
-
-#define MONITOR_LEN    1024
-
-static char    monitor_line[MONITOR_LEN + 1];
-static int     monitor_pos;
-
-void
-aoview_monitor_disconnect(void)
-{
-       if (monitor_serial) {
-               aoview_serial_close(monitor_serial);
-               monitor_serial = NULL;
-       }
-       aoview_log_new();
-}
-
-static void
-aoview_parse_string(char *target, int len, char *source)
-{
-       strncpy(target, source, len-1);
-       target[len-1] = '\0';
-}
-
-static void
-aoview_parse_int(int *target, char *source)
-{
-       *target = strtol(source, NULL, 0);
-}
-
-static void
-aoview_parse_hex(int *target, char *source)
-{
-       *target = strtol(source, NULL, 16);
-}
-
-static void
-aoview_parse_pos(double *target, char *source)
-{
-       int     deg;
-       double  min;
-       char    dir;
-       double  r;
-
-       if (sscanf(source, "%d°%lf'%c", &deg, &min, &dir) != 3) {
-               *target = 0;
-               return;
-       }
-       r = deg + min / 60.0;
-       if (dir == 'S' || dir == 'W')
-               r = -r;
-       *target = r;
-}
-
-#define PARSE_MAX_WORDS        256
-
-gboolean
-aoview_monitor_parse(const char *input_line)
-{
-       char *saveptr;
-       char *words[PARSE_MAX_WORDS];
-       int nword;
-       char line_buf[8192], *line;
-       struct aodata   data;
-       int     tracking_pos;
-
-       /* avoid smashing our input parameter */
-       strncpy (line_buf, input_line, sizeof (line_buf)-1);
-       line_buf[sizeof(line_buf) - 1] = '\0';
-       line = line_buf;
-       for (nword = 0; nword < PARSE_MAX_WORDS; nword++) {
-               words[nword] = strtok_r(line, " \t\n", &saveptr);
-               line = NULL;
-               if (words[nword] == NULL)
-                       break;
-       }
-       if (nword < 36)
-               return FALSE;
-       if (strcmp(words[0], "CALL") != 0)
-               return FALSE;
-       aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]);
-       aoview_parse_int(&data.serial, words[3]);
-
-       aoview_parse_int(&data.rssi, words[5]);
-       aoview_parse_string(data.state, sizeof (data.state), words[9]);
-       aoview_parse_int(&data.tick, words[10]);
-       aoview_parse_int(&data.accel, words[12]);
-       aoview_parse_int(&data.pres, words[14]);
-       aoview_parse_int(&data.temp, words[16]);
-       aoview_parse_int(&data.batt, words[18]);
-       aoview_parse_int(&data.drogue, words[20]);
-       aoview_parse_int(&data.main, words[22]);
-       aoview_parse_int(&data.flight_accel, words[24]);
-       aoview_parse_int(&data.ground_accel, words[26]);
-       aoview_parse_int(&data.flight_vel, words[28]);
-       aoview_parse_int(&data.flight_pres, words[30]);
-       aoview_parse_int(&data.ground_pres, words[32]);
-       aoview_parse_int(&data.gps.nsat, words[34]);
-       if (strcmp (words[36], "unlocked") == 0) {
-               data.gps.gps_connected = 1;
-               data.gps.gps_locked = 0;
-               data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0;
-               data.gps.lat = data.gps.lon = 0;
-               data.gps.alt = 0;
-               tracking_pos = 37;
-       } else if (nword >= 40) {
-               data.gps.gps_locked = 1;
-               data.gps.gps_connected = 1;
-               sscanf(words[36], "%d:%d:%d", &data.gps.gps_time.hour, &data.gps.gps_time.minute, &data.gps.gps_time.second);
-               aoview_parse_pos(&data.gps.lat, words[37]);
-               aoview_parse_pos(&data.gps.lon, words[38]);
-               sscanf(words[39], "%dm", &data.gps.alt);
-               tracking_pos = 46;
-       } else {
-               data.gps.gps_connected = 0;
-               data.gps.gps_locked = 0;
-               data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0;
-               data.gps.lat = data.gps.lon = 0;
-               data.gps.alt = 0;
-               tracking_pos = -1;
-       }
-       if (nword >= 46) {
-               data.gps.gps_extended = 1;
-               sscanf(words[40], "%lfm/s", &data.gps.ground_speed);
-               sscanf(words[41], "%d", &data.gps.course);
-               sscanf(words[42], "%lfm/s", &data.gps.climb_rate);
-               sscanf(words[43], "%lf", &data.gps.hdop);
-               sscanf(words[44], "%d", &data.gps.h_error);
-               sscanf(words[45], "%d", &data.gps.v_error);
-       } else {
-               data.gps.gps_extended = 0;
-               data.gps.ground_speed = 0;
-               data.gps.course = 0;
-               data.gps.climb_rate = 0;
-               data.gps.hdop = 0;
-               data.gps.h_error = 0;
-               data.gps.v_error = 0;
-       }
-       if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) {
-               int     c, n, pos;
-               aoview_parse_int(&n, words[tracking_pos + 1]);
-               pos = tracking_pos + 2;
-               if (nword >= pos + n * 3) {
-                       data.gps_tracking.channels = n;
-                       for (c = 0; c < n; c++) {
-                               aoview_parse_int(&data.gps_tracking.sats[c].svid,
-                                                words[pos + 0]);
-                               aoview_parse_hex(&data.gps_tracking.sats[c].state,
-                                                words[pos + 1]);
-                               aoview_parse_int(&data.gps_tracking.sats[c].c_n0,
-                                                words[pos + 2]);
-                               pos += 3;
-                       }
-               } else {
-                       data.gps_tracking.channels = 0;
-               }
-       } else {
-               data.gps_tracking.channels = 0;
-       }
-       aoview_state_notify(&data);
-       return TRUE;
-}
-
-static void
-aoview_monitor_callback(gpointer user_data,
-                       struct aoview_serial *serial,
-                       gint revents)
-{
-       int     c;
-
-       if (revents & (G_IO_HUP|G_IO_ERR)) {
-               aoview_monitor_disconnect();
-               return;
-       }
-       if (revents & G_IO_IN) {
-               for (;;) {
-                       c = aoview_serial_getc(serial);
-                       if (c == -1)
-                               break;
-                       if (c == '\r')
-                               continue;
-                       if (c == '\n') {
-                               monitor_line[monitor_pos] = '\0';
-                               if (monitor_pos) {
-                                       if (aoview_monitor_parse(monitor_line)) {
-                                               aoview_log_set_serial(aostate.data.serial);
-                                               if (aoview_log_get_serial())
-                                                       aoview_log_printf ("%s\n", monitor_line);
-                                       }
-                               }
-                               monitor_pos = 0;
-                       } else if (monitor_pos < MONITOR_LEN)
-                               monitor_line[monitor_pos++] = c;
-               }
-       }
-}
-
-gboolean
-aoview_monitor_connect(char *tty)
-{
-       aoview_monitor_disconnect();
-       monitor_serial = aoview_serial_open(tty);
-       if (!monitor_serial)
-               return FALSE;
-       aoview_table_clear();
-       aoview_state_reset();
-       aoview_serial_set_callback(monitor_serial,
-                                  aoview_monitor_callback);
-       return TRUE;
-}
diff --git a/ao-view/aoview_replay.c b/ao-view/aoview_replay.c
deleted file mode 100644 (file)
index da7b5d6..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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 GtkFileChooser  *replay_dialog;
-static GtkWidget       *replay_ok;
-static FILE            *replay_file;
-static int             replay_tick;
-
-static int
-find_tick(char *line, gboolean *is_pad)
-{
-       char    *state = strstr(line, "STATE");
-       if (!state)
-               return -1;
-       state = strchr(state, ' ');
-       if (!state)
-               return -1;
-       while (*state == ' ')
-               state++;
-       *is_pad = strncmp(state, "pad", 3) == 0;
-       while (*state && !isdigit(*state))
-               state++;
-       return atoi(state);
-}
-
-static void
-aoview_replay_close(void)
-{
-       if (replay_file) {
-               fclose(replay_file);
-               replay_file = NULL;
-       }
-}
-
-static char    replay_line[1024];
-
-static gboolean
-aoview_replay_read(gpointer data);
-
-static gboolean
-aoview_replay_execute(gpointer data)
-{
-       aoview_monitor_parse(replay_line);
-       g_idle_add(aoview_replay_read, NULL);
-       return FALSE;
-}
-
-static gboolean
-aoview_replay_read(gpointer data)
-{
-       int             tick;
-       gboolean        is_pad;
-
-       if (!replay_file)
-               return FALSE;
-       if (fgets(replay_line, sizeof (replay_line), replay_file)) {
-               tick = find_tick(replay_line, &is_pad);
-               if (tick >= 0 && replay_tick >= 0 && !is_pad) {
-                       while (tick < replay_tick)
-                               tick += 65536;
-                       g_timeout_add((tick - replay_tick) * 10,
-                                     aoview_replay_execute,
-                                     NULL);
-               } else {
-                       aoview_replay_execute(NULL);
-               }
-               replay_tick = tick;
-       } else {
-               aoview_replay_close();
-       }
-       return FALSE;
-}
-
-static void
-aoview_replay_open(GtkWidget *widget, gpointer data)
-{
-       char            *replay_file_name;
-       GtkWidget       *dialog;
-
-       aoview_replay_close();
-       replay_file_name = gtk_file_chooser_get_filename(replay_dialog);
-       replay_file = fopen(replay_file_name, "r");
-       if (!replay_file) {
-               dialog = gtk_message_dialog_new(GTK_WINDOW(replay_dialog),
-                                               GTK_DIALOG_DESTROY_WITH_PARENT,
-                                               GTK_MESSAGE_ERROR,
-                                               GTK_BUTTONS_CLOSE,
-                                               "Error loading file '%s': %s",
-                                               replay_file_name, g_strerror(errno));
-               gtk_dialog_run(GTK_DIALOG(dialog));
-               gtk_widget_destroy(dialog);
-       } else {
-               replay_tick = -1;
-               aoview_state_reset();
-               aoview_replay_read(NULL);
-       }
-       gtk_widget_hide(GTK_WIDGET(replay_dialog));
-}
-
-void
-aoview_replay_init(GladeXML *xml)
-{
-       GtkFileFilter   *telem_filter;
-       GtkFileFilter   *all_filter;
-       GtkFileFilter   *log_filter;
-
-       telem_filter = gtk_file_filter_new();
-       gtk_file_filter_add_pattern(telem_filter, "*.telem");
-       gtk_file_filter_set_name(telem_filter, "Telemetry Files");
-
-       log_filter = gtk_file_filter_new();
-       gtk_file_filter_add_pattern(log_filter, "*.log");
-       gtk_file_filter_set_name(log_filter, "Log Files");
-
-       all_filter = gtk_file_filter_new();
-       gtk_file_filter_add_pattern(all_filter, "*");
-       gtk_file_filter_set_name(all_filter, "All Files");
-
-       replay_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "ao_replay_dialog"));
-       assert(replay_dialog);
-       gtk_file_chooser_set_current_folder(replay_dialog, aoview_file_dir);
-       gtk_file_chooser_add_filter(replay_dialog, telem_filter);
-       gtk_file_chooser_add_filter(replay_dialog, log_filter);
-       gtk_file_chooser_add_filter(replay_dialog, all_filter);
-
-       replay_ok = glade_xml_get_widget(xml, "ao_replay_ok");
-       assert(replay_ok);
-       g_signal_connect(G_OBJECT(replay_ok), "clicked",
-                        G_CALLBACK(aoview_replay_open),
-                        replay_dialog);
-}
diff --git a/ao-view/aoview_serial.c b/ao-view/aoview_serial.c
deleted file mode 100644 (file)
index 29038b7..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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"
-#include <termios.h>
-
-#define AOVIEW_SERIAL_IN_BUF   64
-#define AOVIEW_SERIAL_OUT_BUF  64
-
-struct aoview_buf {
-       char            *buf;
-       int             off;
-       int             count;
-       int             size;
-};
-
-static int
-aoview_buf_write(struct aoview_buf *buf, char *data, int len)
-{
-       if (buf->count + len > buf->size) {
-               int     new_size = buf->size * 2;
-               if (new_size == 0)
-                       new_size = 1024;
-               if (buf->buf)
-                       buf->buf = realloc (buf->buf, new_size);
-               else
-                       buf->buf = malloc (new_size);
-               buf->size = new_size;
-       }
-       memcpy(buf->buf + buf->count, data, len);
-       buf->count += len;
-       return len;
-}
-
-static int
-aoview_buf_read(struct aoview_buf *buf, char *data, int len)
-{
-       if (len > buf->count - buf->off)
-               len = buf->count - buf->off;
-       memcpy (data, buf->buf + buf->off, len);
-       buf->off += len;
-       if (buf->off == buf->count)
-               buf->off = buf->count = 0;
-       return len;
-}
-
-static int
-aoview_buf_getc(struct aoview_buf *buf)
-{
-       char    b;
-       int     r;
-
-       r = aoview_buf_read(buf, &b, 1);
-       if (r == 1)
-               return (int) b;
-       return -1;
-}
-
-static void
-aoview_buf_flush(struct aoview_buf *buf, int fd)
-{
-       int     ret;
-
-       if (buf->count > buf->off) {
-               ret = write(fd, buf->buf + buf->off, buf->count - buf->off);
-               if (ret > 0) {
-                       buf->off += ret;
-                       if (buf->off == buf->count)
-                               buf->off = buf->count = 0;
-               }
-       }
-}
-
-static void
-aoview_buf_fill(struct aoview_buf *buf, int fd)
-{
-       int ret;
-
-       while (buf->count >= buf->size) {
-               int new_size = buf->size * 2;
-               buf->buf = realloc (buf->buf, new_size);
-               buf->size = new_size;
-       }
-
-       ret = read(fd, buf->buf + buf->count, buf->size - buf->count);
-       if (ret > 0)
-               buf->count += ret;
-}
-
-static void
-aoview_buf_init(struct aoview_buf *buf)
-{
-       buf->buf = malloc (buf->size = 1024);
-       buf->count = 0;
-}
-
-static void
-aoview_buf_fini(struct aoview_buf *buf)
-{
-       free(buf->buf);
-}
-
-struct aoview_serial {
-       GSource                 source;
-       int                     fd;
-       struct termios          save_termios;
-       struct aoview_buf       in_buf;
-       struct aoview_buf       out_buf;
-       GPollFD                 poll_fd;
-};
-
-
-void
-aoview_serial_printf(struct aoview_serial *serial, char *format, ...)
-{
-       char    buf[1024];
-       va_list ap;
-       int     ret;
-
-       /* sprintf to a local buffer */
-       va_start(ap, format);
-       ret = vsnprintf(buf, sizeof(buf), format, ap);
-       va_end(ap);
-       if (ret > sizeof(buf)) {
-               fprintf(stderr, "printf overflow for format %s\n",
-                       format);
-       }
-
-       /* flush local buffer to the wire */
-       aoview_buf_write(&serial->out_buf, buf, ret);
-       aoview_buf_flush(&serial->out_buf, serial->fd);
-}
-
-int
-aoview_serial_read(struct aoview_serial *serial, char *buf, int len)
-{
-       return aoview_buf_read(&serial->in_buf, buf, len);
-}
-
-int
-aoview_serial_getc(struct aoview_serial *serial)
-{
-       return aoview_buf_getc(&serial->in_buf);
-}
-
-static gboolean
-serial_prepare(GSource *source, gint *timeout)
-{
-       struct aoview_serial *serial = (struct aoview_serial *) source;
-       *timeout = -1;
-
-       if (serial->out_buf.count)
-               serial->poll_fd.events |= G_IO_OUT;
-       else
-               serial->poll_fd.events &= ~G_IO_OUT;
-       return FALSE;
-}
-
-static gboolean
-serial_check(GSource *source)
-{
-       struct aoview_serial *serial = (struct aoview_serial *) source;
-       gint revents = serial->poll_fd.revents;
-
-       if (revents & G_IO_NVAL)
-               return FALSE;
-       if (revents & G_IO_IN)
-               return TRUE;
-       if (revents & G_IO_OUT)
-               return TRUE;
-       return FALSE;
-}
-
-static gboolean
-serial_dispatch(GSource *source,
-               GSourceFunc callback,
-               gpointer user_data)
-{
-       struct aoview_serial *serial = (struct aoview_serial *) source;
-       aoview_serial_callback func = (aoview_serial_callback) callback;
-       gint revents = serial->poll_fd.revents;
-
-       if (revents & G_IO_IN)
-               aoview_buf_fill(&serial->in_buf, serial->fd);
-
-       if (revents & G_IO_OUT)
-               aoview_buf_flush(&serial->out_buf, serial->fd);
-
-       if (func)
-               (*func)(user_data, serial, revents);
-       return TRUE;
-}
-
-static void
-serial_finalize(GSource *source)
-{
-       struct aoview_serial *serial = (struct aoview_serial *) source;
-
-       aoview_buf_fini(&serial->in_buf);
-       aoview_buf_fini(&serial->out_buf);
-       tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios);
-       close (serial->fd);
-}
-
-static GSourceFuncs serial_funcs = {
-       serial_prepare,
-       serial_check,
-       serial_dispatch,
-       serial_finalize
-};
-
-struct aoview_serial *
-aoview_serial_open(const char *tty)
-{
-       struct aoview_serial    *serial;
-       struct termios  termios;
-
-       serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial));
-       aoview_buf_init(&serial->in_buf);
-       aoview_buf_init(&serial->out_buf);
-       serial->fd = open (tty, O_RDWR | O_NONBLOCK);
-       if (serial->fd < 0) {
-               g_source_destroy(&serial->source);
-               return NULL;
-       }
-       tcgetattr(serial->fd, &termios);
-       serial->save_termios = termios;
-       cfmakeraw(&termios);
-       tcsetattr(serial->fd, TCSAFLUSH, &termios);
-
-       aoview_serial_printf(serial, "E 0\n");
-       tcdrain(serial->fd);
-       usleep(15*1000);
-       tcflush(serial->fd, TCIFLUSH);
-       serial->poll_fd.fd = serial->fd;
-       serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
-       g_source_attach(&serial->source, NULL);
-       g_source_add_poll(&serial->source,&serial->poll_fd);
-       aoview_serial_set_callback(serial, NULL);
-       return serial;
-}
-
-void
-aoview_serial_close(struct aoview_serial *serial)
-{
-       g_source_remove_poll(&serial->source, &serial->poll_fd);
-       close(serial->fd);
-       g_source_destroy(&serial->source);
-}
-
-void
-aoview_serial_set_callback(struct aoview_serial *serial,
-                          aoview_serial_callback func)
-{
-       g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL);
-}
diff --git a/ao-view/aoview_state.c b/ao-view/aoview_state.c
deleted file mode 100644 (file)
index f75066d..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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"
-#include <math.h>
-
-static inline double sqr(double a) { return a * a; };
-
-static void
-aoview_great_circle (double start_lat, double start_lon,
-                    double end_lat, double end_lon,
-                    double *dist, double *bearing)
-{
-       const double rad = M_PI / 180;
-       const double earth_radius = 6371.2 * 1000;      /* in meters */
-       double lat1 = rad * start_lat;
-       double lon1 = rad * -start_lon;
-       double lat2 = rad * end_lat;
-       double lon2 = rad * -end_lon;
-
-       double d_lat = lat2 - lat1;
-       double d_lon = lon2 - lon1;
-
-       /* From http://en.wikipedia.org/wiki/Great-circle_distance */
-       double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) +
-                         sqr(cos(lat1) * sin(lat2) -
-                             sin(lat1) * cos(lat2) * cos(d_lon)));
-       double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon);
-       double d = atan2(vdn,vdd);
-       double course;
-
-       if (cos(lat1) < 1e-20) {
-               if (lat1 > 0)
-                       course = M_PI;
-               else
-                       course = -M_PI;
-       } else {
-               if (d < 1e-10)
-                       course = 0;
-               else
-                       course = acos((sin(lat2)-sin(lat1)*cos(d)) /
-                                     (sin(d)*cos(lat1)));
-               if (sin(lon2-lon1) > 0)
-                       course = 2 * M_PI-course;
-       }
-       *dist = d * earth_radius;
-       *bearing = course * 180/M_PI;
-}
-
-static void
-aoview_state_add_deg(int column, char *label, double deg, char pos, char neg)
-{
-       double  int_part;
-       double  min;
-       char    sign = pos;
-
-       if (deg < 0) {
-               deg = -deg;
-               sign = neg;
-       }
-       int_part = floor (deg);
-       min = (deg - int_part) * 60.0;
-       aoview_table_add_row(column, label, "%d°%lf'%c",
-                            (int) int_part, min, sign);
-
-}
-
-static char *ascent_states[] = {
-       "boost",
-       "fast",
-       "coast",
-       0,
-};
-
-static double
-aoview_time(void)
-{
-       struct timespec now;
-
-       clock_gettime(CLOCK_MONOTONIC, &now);
-       return (double) now.tv_sec + (double) now.tv_nsec / 1.0e9;
-}
-
-/*
- * Fill out the derived data fields
- */
-static void
-aoview_state_derive(struct aodata *data, struct aostate *state)
-{
-       int     i;
-       double  new_height;
-       double  height_change;
-       double  time_change;
-       int     tick_count;
-
-       state->report_time = aoview_time();
-
-       state->prev_data = state->data;
-       state->prev_npad = state->npad;
-       state->data = *data;
-       tick_count = data->tick;
-       if (tick_count < state->prev_data.tick)
-               tick_count += 65536;
-       time_change = (tick_count - state->prev_data.tick) / 100.0;
-
-       state->ground_altitude = aoview_pres_to_altitude(data->ground_pres);
-       new_height = aoview_pres_to_altitude(data->flight_pres) - state->ground_altitude;
-       height_change = new_height - state->height;
-       state->height = new_height;
-       if (time_change)
-               state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0;
-       state->acceleration = (data->ground_accel - data->flight_accel) / 27.0;
-       state->speed = data->flight_vel / 2700.0;
-       state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01;
-       state->drogue_sense = data->drogue / 32767.0 * 15.0;
-       state->main_sense = data->main / 32767.0 * 15.0;
-       state->battery = data->batt / 32767.0 * 5.0;
-       if (!strcmp(data->state, "pad")) {
-               if (data->gps.gps_locked && data->gps.nsat >= 4) {
-                       state->npad++;
-                       state->pad_lat_total += data->gps.lat;
-                       state->pad_lon_total += data->gps.lon;
-                       state->pad_alt_total += data->gps.alt;
-                       if (state->npad > 1) {
-                               state->pad_lat = (state->pad_lat * 31 + data->gps.lat) / 32.0;
-                               state->pad_lon = (state->pad_lon * 31 + data->gps.lon) / 32.0;
-                               state->pad_alt = (state->pad_alt * 31 + data->gps.alt) / 32.0;
-                       } else {
-                               state->pad_lat = data->gps.lat;
-                               state->pad_lon = data->gps.lon;
-                               state->pad_alt = data->gps.alt;
-                       }
-               }
-       }
-       state->ascent = FALSE;
-       for (i = 0; ascent_states[i]; i++)
-               if (!strcmp(data->state, ascent_states[i]))
-                       state->ascent = TRUE;
-
-       /* Only look at accelerometer data on the way up */
-       if (state->ascent && state->acceleration > state->max_acceleration)
-               state->max_acceleration = state->acceleration;
-       if (state->ascent && state->speed > state->max_speed)
-               state->max_speed = state->speed;
-
-       if (state->height > state->max_height)
-               state->max_height = state->height;
-       state->gps.gps_locked = data->gps.gps_locked;
-       state->gps.gps_connected = data->gps.gps_connected;
-       if (data->gps.gps_locked) {
-               state->gps = data->gps;
-               state->gps_valid = 1;
-               if (state->npad)
-                       aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon,
-                                           &state->distance, &state->bearing);
-       }
-       if (data->gps_tracking.channels)
-               state->gps_tracking = data->gps_tracking;
-       if (state->npad) {
-               state->gps_height = state->gps.alt - state->pad_alt;
-       } else {
-               state->gps_height = 0;
-       }
-}
-
-void
-aoview_speak_state(struct aostate *state)
-{
-       if (strcmp(state->data.state, state->prev_data.state)) {
-               aoview_voice_speak("%s\n", state->data.state);
-               if (!strcmp(state->data.state, "drogue"))
-                       aoview_voice_speak("apogee %d meters\n",
-                                          (int) state->max_height);
-               if (!strcmp(state->prev_data.state, "boost"))
-                       aoview_voice_speak("max speed %d meters per second\n",
-                                          (int) state->max_speed);
-       }
-       if (state->prev_npad < MIN_PAD_SAMPLES && state->npad >= MIN_PAD_SAMPLES)
-               aoview_voice_speak("g p s ready\n");
-}
-
-void
-aoview_speak_height(struct aostate *state)
-{
-       aoview_voice_speak("%d meters\n", state->height);
-}
-
-struct aostate aostate;
-
-static guint aostate_timeout;
-
-#define COMPASS_LIMIT(n)       ((n * 22.5) + 22.5/2)
-
-static char *compass_points[] = {
-       "north",
-       "north north east",
-       "north east",
-       "east north east",
-       "east",
-       "east south east",
-       "south east",
-       "south south east",
-       "south",
-       "south south west",
-       "south west",
-       "west south west",
-       "west",
-       "west north west",
-       "north west",
-       "north north west",
-};
-
-static char *
-aoview_compass_point(double bearing)
-{
-       int     i;
-       while (bearing < 0)
-               bearing += 360.0;
-       while (bearing >= 360.0)
-               bearing -= 360.0;
-
-       i = floor ((bearing - 22.5/2) / 22.5 + 0.5);
-       if (i < 0) i = 0;
-       if (i >= sizeof (compass_points) / sizeof (compass_points[0]))
-               i = 0;
-       return compass_points[i];
-}
-
-static gboolean
-aoview_state_timeout(gpointer data)
-{
-       double  now = aoview_time();
-
-       if (strlen(aostate.data.state) > 0 && strcmp(aostate.data.state, "pad") != 0)
-               aoview_speak_height(&aostate);
-       if (now - aostate.report_time >= 20 || !strcmp(aostate.data.state, "landed")) {
-               if (!aostate.ascent) {
-                       if (fabs(aostate.baro_speed) < 20 && aostate.height < 100)
-                               aoview_voice_speak("rocket landed safely\n");
-                       else
-                               aoview_voice_speak("rocket may have crashed\n");
-                       if (aostate.gps_valid) {
-                               aoview_voice_speak("rocket reported %s of pad distance %d meters\n",
-                                                  aoview_compass_point(aostate.bearing),
-                                                  (int) aostate.distance);
-                       }
-               }
-               aostate_timeout = 0;
-               return FALSE;
-       }
-       return TRUE;
-}
-
-void
-aoview_state_reset(void)
-{
-       memset(&aostate, '\0', sizeof (aostate));
-}
-
-void
-aoview_state_notify(struct aodata *data)
-{
-       struct aostate *state = &aostate;
-       aoview_state_derive(data, state);
-       aoview_table_start();
-
-       if (state->npad >= MIN_PAD_SAMPLES)
-               aoview_table_add_row(0, "Ground state", "ready");
-       else
-               aoview_table_add_row(0, "Ground state", "waiting for gps (%d)",
-                                    MIN_PAD_SAMPLES - state->npad);
-       aoview_table_add_row(0, "Rocket state", "%s", state->data.state);
-       aoview_table_add_row(0, "Callsign", "%s", state->data.callsign);
-       aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial);
-
-       aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi);
-       aoview_table_add_row(0, "Height", "%6dm", state->height);
-       aoview_table_add_row(0, "Max height", "%6dm", state->max_height);
-       aoview_table_add_row(0, "Acceleration", "%7.1fm/s²", state->acceleration);
-       aoview_table_add_row(0, "Max acceleration", "%7.1fm/s²", state->max_acceleration);
-       aoview_table_add_row(0, "Speed", "%7.1fm/s", state->ascent ? state->speed : state->baro_speed);
-       aoview_table_add_row(0, "Max Speed", "%7.1fm/s", state->max_speed);
-       aoview_table_add_row(0, "Temperature", "%6.2f°C", state->temperature);
-       aoview_table_add_row(0, "Battery", "%5.2fV", state->battery);
-       aoview_table_add_row(0, "Drogue", "%5.2fV", state->drogue_sense);
-       aoview_table_add_row(0, "Main", "%5.2fV", state->main_sense);
-       aoview_table_add_row(0, "Pad altitude", "%dm", state->ground_altitude);
-       aoview_table_add_row(1, "Satellites", "%d", state->gps.nsat);
-       if (state->gps.gps_locked) {
-               aoview_table_add_row(1, "GPS", "locked");
-       } else if (state->gps.gps_connected) {
-               aoview_table_add_row(1, "GPS", "unlocked");
-       } else {
-               aoview_table_add_row(1, "GPS", "not available");
-       }
-       if (state->gps_valid) {
-               aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S');
-               aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W');
-               aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt);
-               aoview_table_add_row(1, "GPS height", "%d", state->gps_height);
-               aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d",
-                                    state->gps.gps_time.hour,
-                                    state->gps.gps_time.minute,
-                                    state->gps.gps_time.second);
-       }
-       if (state->gps.gps_extended) {
-               aoview_table_add_row(1, "GPS ground speed", "%7.1fm/s %d°",
-                                    state->gps.ground_speed,
-                                    state->gps.course);
-               aoview_table_add_row(1, "GPS climb rate", "%7.1fm/s",
-                                    state->gps.climb_rate);
-               aoview_table_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)",
-                                    state->gps.hdop, state->gps.h_error, state->gps.v_error);
-       }
-       if (state->npad) {
-               aoview_table_add_row(1, "Distance from pad", "%5.0fm", state->distance);
-               aoview_table_add_row(1, "Direction from pad", "%4.0f°", state->bearing);
-               aoview_state_add_deg(1, "Pad latitude", state->pad_lat, 'N', 'S');
-               aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W');
-               aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt);
-       }
-       if (state->gps.gps_connected) {
-               int     nsat_vis = 0;
-               int     nsat_locked = 0;
-               int     c;
-
-               for (c = 0; c < state->gps_tracking.channels; c++) {
-                       if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf)
-                               nsat_locked++;
-               }
-               aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels);
-               aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked);
-               for (c = 0; c < state->gps_tracking.channels; c++) {
-                       aoview_table_add_row(2, "Satellite id,state,C/N0",
-                                            "%3d,%02x,%2d%s",
-                                            state->gps_tracking.sats[c].svid,
-                                            state->gps_tracking.sats[c].state,
-                                            state->gps_tracking.sats[c].c_n0,
-                                            (state->gps_tracking.sats[c].state & 0xff) == 0xbf ?
-                                            " LOCKED" : "");
-               }
-       }
-       aoview_table_finish();
-       aoview_label_show(state);
-       aoview_speak_state(state);
-       if (!aostate_timeout && strcmp(state->data.state, "pad") != 0)
-               aostate_timeout = g_timeout_add_seconds(10, aoview_state_timeout, NULL);
-}
-
-void
-aoview_state_new(void)
-{
-}
-
-void
-aoview_state_init(GladeXML *xml)
-{
-       aoview_state_new();
-}
diff --git a/ao-view/aoview_table.c b/ao-view/aoview_table.c
deleted file mode 100644 (file)
index e75ae67..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 NCOL   3
-
-static GtkTreeView     *dataview[NCOL];
-static GtkListStore    *datalist[NCOL];
-
-void
-aoview_table_start(void)
-{
-       int col;
-       for (col = 0; col < NCOL; col++)
-               datalist[col] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
-}
-
-void
-aoview_table_add_row(int col, 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[col], &iter);
-       gtk_list_store_set(datalist[col], &iter,
-                          0, label,
-                          1, buf,
-                          -1);
-}
-
-void
-aoview_table_finish(void)
-{
-       int     col;
-       for (col = 0; col < NCOL; col++) {
-               gtk_tree_view_set_model(dataview[col], GTK_TREE_MODEL(datalist[col]));
-               g_object_unref(G_OBJECT(datalist[col]));
-               gtk_tree_view_columns_autosize(dataview[col]);
-       }
-}
-
-void
-aoview_table_clear(void)
-{
-       int     col;
-       for (col = 0; col < NCOL; col++)
-               gtk_tree_view_set_model(dataview[col], NULL);
-}
-
-void
-aoview_table_init(GladeXML *xml)
-{
-       int     col;
-
-       for (col = 0; col < NCOL; col++) {
-               char    name[32];
-               sprintf(name, "dataview_%d", col);
-               dataview[col] = GTK_TREE_VIEW(glade_xml_get_widget(xml, name));
-               assert(dataview[col]);
-
-               aoview_add_plain_text_column(dataview[col], "Field", 0, 20);
-               aoview_add_plain_text_column(dataview[col], "Value", 1, 32);
-       }
-}
diff --git a/ao-view/aoview_util.c b/ao-view/aoview_util.c
deleted file mode 100644 (file)
index 6ea62ac..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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;
-}
diff --git a/ao-view/aoview_voice.c b/ao-view/aoview_voice.c
deleted file mode 100644 (file)
index 24422df..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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"
-
-#if HAVE_FLITE
-#include <stdarg.h>
-
-FILE   *aoview_flite;
-
-void aoview_voice_open(void)
-{
-       int     err;
-
-       if (!aoview_flite)
-               aoview_flite = aoview_flite_start();
-}
-
-void aoview_voice_close(void)
-{
-       if (aoview_flite) {
-               aoview_flite_stop();
-               aoview_flite = NULL;
-       }
-}
-
-void aoview_voice_speak(char *format, ...)
-{
-       va_list ap;
-
-       if (aoview_flite) {
-               va_start(ap, format);
-               vfprintf(aoview_flite, format, ap);
-               fflush(aoview_flite);
-               va_end(ap);
-       }
-}
-
-#else
-void aoview_voice_open(void)
-{
-}
-
-void aoview_voice_close(void)
-{
-}
-
-void aoview_voice_speak(char *format, ...)
-{
-}
-#endif
-
-
-static GtkCheckMenuItem        *voice_enable;
-
-#define ALTOS_VOICE_PATH       "/apps/aoview/voice"
-
-static void
-aoview_voice_enable(GtkWidget *widget, gpointer data)
-{
-       gboolean        enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
-       GError          *error;
-       GConfClient     *gconf_client;
-
-       if (enabled) {
-               aoview_voice_open();
-               aoview_voice_speak("enable voice\n");
-       } else {
-               aoview_voice_speak("disable voice\n");
-               aoview_voice_close();
-       }
-       gconf_client = gconf_client_get_default();
-       gconf_client_set_bool(gconf_client,
-                             ALTOS_VOICE_PATH,
-                             enabled,
-                             &error);
-}
-
-void
-aoview_voice_init(GladeXML *xml)
-{
-       gboolean        enabled;
-       GConfClient     *gconf_client;
-
-       voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable"));
-       assert(voice_enable);
-
-       gconf_client = gconf_client_get_default();
-       enabled = TRUE;
-       if (gconf_client)
-       {
-               GError  *error;
-
-               error = NULL;
-               enabled = gconf_client_get_bool(gconf_client,
-                                               ALTOS_VOICE_PATH,
-                                               &error);
-               if (error)
-                       enabled = TRUE;
-       }
-       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(voice_enable), enabled);
-       if (enabled)
-               aoview_voice_open();
-
-       g_signal_connect(G_OBJECT(voice_enable), "toggled",
-                        G_CALLBACK(aoview_voice_enable),
-                        voice_enable);
-}
diff --git a/ao-view/design b/ao-view/design
deleted file mode 100644 (file)
index 6ec2ea7..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-Requirements:
-       real-time display of telemetry
-       off-line display of logged data
-       Logging of telemetry
-       Capture of logged data to disk
-
-Input data:
-       accelerometer
-       barometer
-       thermometer
-       gps
-       drogue and main continuity
-       battery voltage
-       time
-       reported flight state
-       reported events
-
-Computed data:
-       velocity (from accelerometer)
-       altitude
-       range
-       direction
-
-Displays:
-       numeric display of current rocket status
-       (graphics come later)
-       text message log
index b52bb6e9c52721b88622c6b8253e52a6ef0cc8b6..dfbae71d8b067ea748f3d335bd84eed25f3d5587 100644 (file)
@@ -73,7 +73,6 @@ PKG_CHECK_MODULES([ALSA], [alsa])
 
 AC_OUTPUT([
 Makefile
-ao-view/Makefile
 ao-tools/Makefile
 ao-tools/lib/Makefile
 ao-tools/ao-rawload/Makefile
@@ -81,5 +80,6 @@ ao-tools/ao-dbg/Makefile
 ao-tools/ao-bitbang/Makefile
 ao-tools/ao-eeprom/Makefile
 ao-tools/ao-load/Makefile
+ao-tools/ao-view/Makefile
 ao-utils/Makefile
 ])