Use flite to announce flight state
authorKeith Packard <keithp@keithp.com>
Tue, 30 Jun 2009 06:05:27 +0000 (23:05 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 30 Jun 2009 06:05:27 +0000 (23:05 -0700)
This uses the flite voice synthesis library from festival to announce
altitude and speed information during the rocket flight.

Signed-off-by: Keith Packard <keithp@keithp.com>
aoview/Makefile.am
aoview/aoview.glade
aoview/aoview.h
aoview/aoview_flite.c [new file with mode: 0644]
aoview/aoview_main.c
aoview/aoview_state.c
aoview/aoview_voice.c [new file with mode: 0644]
configure.ac

index be3fbac..86811bf 100644 (file)
@@ -1,7 +1,11 @@
 VERSION=$(shell git describe)
-AM_CFLAGS=$(GNOME_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
+AM_CFLAGS=$(GNOME_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
 
-bin_PROGRAMS=aoview
+if USE_FLITE
+FLITE_PROG=aoview_flite
+endif
+
+bin_PROGRAMS=aoview $(FLITE_PROG)
 
 aoview_LDADD=$(GNOME_LIBS)
 
@@ -18,8 +22,14 @@ aoview_SOURCES = \
        aoview_util.c \
        aoview_file.c \
        aoview_eeprom.c \
+       aoview_voice.c \
        aoview.h
 
+aoview_flite_SOURCES = \
+       aoview_flite.c
+
+aoview_flite_LDADD=@FLITE_LIBS@
+
 BUILT_SOURCES = aoview_glade.h
 
 CLEANFILES = aoview_glade.h
index f398999..153db1e 100644 (file)
                 </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>
index 6fb5e09..1ad9e16 100644 (file)
@@ -220,4 +220,11 @@ 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, ...);
+
 #endif /* _AOVIEW_H_ */
diff --git a/aoview/aoview_flite.c b/aoview/aoview_flite.c
new file mode 100644 (file)
index 0000000..daa3ed3
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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>
+
+cst_voice *register_cmu_us_kal();
+
+int
+main(int argc, char **argv)
+{
+       char            line[1024];
+       cst_voice       *v;
+
+       flite_init();
+       v = register_cmu_us_kal();
+       if (!v) {
+               perror("register voice");
+               exit(1);
+       }
+       while (fgets(line, sizeof (line) - 1, stdin) != NULL) {
+               flite_text_to_speech(line, v, "play");
+       }
+       exit (0);
+}
index 4590751..6833a84 100644 (file)
@@ -77,6 +77,8 @@ int main(int argc, char **argv)
        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);
index 52f581f..13b0f73 100644 (file)
@@ -73,6 +73,55 @@ aoview_state_add_deg(char *label, double deg, char pos, char neg)
 
 }
 
+static char *ascent_states[] = {
+       "boost",
+       "fast",
+       "coast",
+       0,
+};
+
+void
+aoview_state_speak(struct aostate *state)
+{
+       static char     last_state[32];
+       int             i;
+       gboolean        report = FALSE;
+       static time_t   last_time;
+       time_t          this_time;
+       static int      last_altitude;
+       int             this_altitude;
+
+       if (strcmp(state->state, last_state)) {
+               aoview_voice_speak("rocket state now %s\n", state->state);
+               if (!strcmp(state->state, "drogue"))
+                       aoview_voice_speak("maximum altitude %d meters\n",
+                                          aoview_pres_to_altitude(min_pres) -
+                                          aoview_pres_to_altitude(state->ground_pres));
+               report = TRUE;
+               strcpy(last_state, state->state);
+       }
+       this_time = time(NULL);
+       this_altitude = aoview_pres_to_altitude(state->flight_pres) - aoview_pres_to_altitude(state->ground_pres);
+       if (this_time - last_time >= 10)
+               report = TRUE;
+       if (this_altitude / 1000 != last_altitude / 1000)
+               report = TRUE;
+
+       if (report) {
+               aoview_voice_speak("altitude %d meters\n",
+                                  this_altitude);
+               for (i = 0; ascent_states[i]; i++)
+                       if (!strcmp(ascent_states[i], state->state)) {
+                               aoview_voice_speak("speed %d meters per second\n",
+                                                  state->flight_vel / 2700);
+                               break;
+                       }
+       }
+
+       last_time = this_time;
+       last_altitude = this_altitude;
+}
+
 void
 aoview_state_notify(struct aostate *state)
 {
@@ -171,6 +220,7 @@ aoview_state_notify(struct aostate *state)
                aoview_table_add_row("Pad GPS alt", "%gm", pad_alt);
        }
        aoview_table_finish();
+       aoview_state_speak(state);
 }
 
 void
@@ -193,4 +243,5 @@ void
 aoview_state_init(GladeXML *xml)
 {
        aoview_state_new();
+       aoview_voice_speak("initializing rocket flight monitoring system\n");
 }
diff --git a/aoview/aoview_voice.c b/aoview/aoview_voice.c
new file mode 100644 (file)
index 0000000..7f4e576
--- /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"
+
+#if HAVE_FLITE
+#include <stdarg.h>
+
+FILE   *aoview_flite;
+
+void aoview_voice_open(void)
+{
+       if (!aoview_flite)
+               aoview_flite = popen("aoview_flite", "w");
+}
+
+void aoview_voice_close(void)
+{
+       if (aoview_flite) {
+               pclose(aoview_flite);
+               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;
+
+static void
+aoview_voice_enable(GtkWidget *widget, gpointer data)
+{
+       if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
+               aoview_voice_open();
+               aoview_voice_speak("enable voice system\n");
+       } else {
+               aoview_voice_speak("disable voice system\n");
+               aoview_voice_close();
+       }
+}
+
+void
+aoview_voice_init(GladeXML *xml)
+{
+       aoview_voice_open();
+
+       voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable"));
+       assert(voice_enable);
+
+       g_signal_connect(G_OBJECT(voice_enable), "toggled",
+                        G_CALLBACK(aoview_voice_enable),
+                        voice_enable);
+}
index 178a53f..b2467c3 100644 (file)
@@ -43,6 +43,16 @@ if test "x$GCC" = "xyes"; then
 fi
 AC_SUBST(WARN_CFLAGS)
 
+AC_CHECK_HEADERS(flite/flite.h,HAVE_FLITE_H=yes,HAVE_FLITE_H=no)
+AC_CHECK_LIB(flite, flite_init,HAVE_LIBFLITE=yes,HAVE_LIBFLITE=no,-lm)
+
+if test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes"; then
+       AC_DEFINE(HAVE_FLITE,1,[Define if the flite library is usable])
+       AC_SUBST(FLITE_LIBS,"-lflite_cmu_us_kal -lflite_usenglish -lflite_cmulex -lflite -lm")
+       AC_SUBST(FLITE_INCS,-Iflite)
+fi
+AM_CONDITIONAL(USE_FLITE,test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes")
+
 PKG_CHECK_MODULES([GNOME], [gtk+-2.0 libglade-2.0 gconf-2.0])
 
 PKG_CHECK_MODULES([LIBUSB], [libusb-1.0])