]> err.no Git - mapper/commitdiff
Add speach output using espeak+gstreamer.
authorKaj-Michael Lang <milang@onion.tal.org>
Thu, 9 Aug 2007 09:53:35 +0000 (12:53 +0300)
committerKaj-Michael Lang <milang@onion.tal.org>
Thu, 9 Aug 2007 09:53:35 +0000 (12:53 +0300)
If not enabled, then fallback to using the old fork-flite/espeak mode.

configure.ac
src/Makefile.am
src/mapper.c
src/speak.c [new file with mode: 0644]
src/speak.h [new file with mode: 0644]
src/utils.c

index 75da13681807330161e566c716d210d9b2b2b426..d6f9248b05a2873b28c8fd5764fe88a7fb7a37ca 100644 (file)
@@ -151,6 +151,7 @@ AC_SUBST(SQLITE_CFLAGS)
 PKG_CHECK_MODULES(GSTREAMER, gstreamer-0.10, HAVE_GST=yes, HAVE_GST=no)
 if test "x$HAVE_GST" = "xyes"; then
  AC_DEFINE(WITH_GST, 1, [build with Gstreamer])
+ GSTREAMER_LIBS="$GSTREAMER_LIBS -lgstapp-0.10"
  AC_SUBST(GSTREAMER_LIBS)
  AC_SUBST(GSTREAMER_CFLAGS)
 fi
@@ -171,9 +172,9 @@ AC_CHECK_HEADER(espeak/speak_lib.h)
 ESPEAK_LIBS="-lespeak"
 ESPEAK_CFLAGS="-I/usr/include/espeak"
 AC_CHECK_LIB([espeak], [espeak_Initialize],
-  AC_DEFINE(HAVE_ESPEAK, 1, [Defined if you have espeak])
+  AC_DEFINE(WITH_ESPEAK, 1, [Defined if you have espeak])
   AC_SUBST(ESPEAK_CFLAGS)
-  AC_SUBST(ESPEAK_LIB)
+  AC_SUBST(ESPEAK_LIBS)
 )
 
 # Localisation
index 7095dee0d527ef39ed7f56e0a47a1900c37d9457..f97e8e318ff2fc07cc03cd080d47346fcfea0fa2 100644 (file)
 bin_PROGRAMS = mapper osm2db
 
 mapper_CFLAGS = $(GLIBGTK_CFLAGS) $(OSSO_CFLAGS) $(HILDON_CFLAGS) $(HILDONFM_CFLAGS) \
-       $(GNOME_VFS_CFLAGS) $(GCONF_CFLAGS) $(LIBXML2_CFLAGS) $(GSTREAMER_CFLAGS) \
+       $(GNOME_VFS_CFLAGS) $(GCONF_CFLAGS) $(LIBXML2_CFLAGS) $(GSTREAMER_CFLAGS) $(ESPEAK_CFLAGS) \
        $(SQLITE_CFLAGS) $(LIBCURL_CFLAGS) $(DBUS_GLIB_CFLAGS) $(BLUEZ_CFLAGS)
 
 mapper_LDADD = $(GLIBGTK_LIBS) $(OSSO_LIBS) $(HILDON_LIBS) $(HILDONFM_LIBS) \
-       $(GNOME_VFS_LIBS) $(GCONF_LIBS) $(LIBXML2_LIBS) $(GSTREAMER_LIBS) \
+       $(GNOME_VFS_LIBS) $(GCONF_LIBS) $(LIBXML2_LIBS) $(GSTREAMER_LIBS) $(ESPEAK_LIBS) \
        $(SQLITE_LIBS) $(LIBCURL_LIBS) $(DBUS_GLIB_LIBS) $(BLUEZ_LIBS) -lm
 
 mapper_SOURCES = utils.c \
@@ -55,6 +55,7 @@ mapper_SOURCES = utils.c \
        hildon-wrappers.c \
        ui-common.c \
        config-gconf.c \
+       speak.c \
        mapper.c
 
 osm2db_CFLAGS = $(EXPAT_CFLAGS) $(SQLITE_CFLAGS) $(GLIBGTK_CFLAGS)
index 77210ef303aa63b1e578d2a665370c6b48d85c50..47fc90e0cc4e0a31a30c6f9fa05d77d4642b9e63 100644 (file)
@@ -36,7 +36,9 @@
 #include <errno.h>
 #include <sys/wait.h>
 #include <glib/gstdio.h>
+#ifdef WITH_GST
 #include <gst/gst.h>
+#endif
 #include <gtk/gtk.h>
 #include <fcntl.h>
 #include <gdk/gdkkeysyms.h>
@@ -60,6 +62,7 @@
 #include "ui-common.h"
 #include "db.h"
 #include "cb.h"
+#include "speak.h"
 
 gfloat UNITS_CONVERT[] = {1.85200,1.15077945,1.f,};
 
@@ -205,7 +208,10 @@ gint main(gint argc, gchar * argv[])
                return 1;
 #endif
        set_var_defaults();     
+#ifdef WITH_GST
        gst_init(&argc, &argv);
+       speak_init();
+#endif
        gtk_init(&argc, &argv);
        gconf_init(argc, argv, NULL);
        gnome_vfs_init();
@@ -219,6 +225,9 @@ gint main(gint argc, gchar * argv[])
 #endif
        gtk_main();
        mapper_destroy();
+#ifdef WITH_GST
+       speak_deinit();
+#endif
 #ifdef WITH_OSSO
        osso_deinitialize(_osso);
 #endif
diff --git a/src/speak.c b/src/speak.c
new file mode 100644 (file)
index 0000000..11d1bad
--- /dev/null
@@ -0,0 +1,229 @@
+#include "config.h"
+
+#if defined (WITH_GST) && defined (WITH_ESPEAK)
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappbuffer.h>
+#include <gst/app/gstappsink.h>
+#include <espeak/speak_lib.h>
+
+#ifndef WITH_DEVICE_770
+#define AUDIO_SINK "autoaudiosink"
+#else
+#define AUDIO_SINK "dsppcmsink"
+#endif
+
+#include "speak.h"
+
+typedef struct _gst_espeak gst_espeak;
+struct _gst_espeak {
+       GstCaps *srccaps;
+       GstElement *pipeline;
+       GstElement *src;
+       GstElement *queue;
+       GstElement *caps;
+       GstElement *conv;
+       GstElement *sink;
+       gboolean done;
+       gshort  *buffer;
+       gint size;
+};
+static gst_espeak ge;
+
+static gint erate;
+static GstBus *bus;
+static gboolean speaking=FALSE;
+
+static gboolean
+bus_call (GstBus *bus, GstMessage *msg, gpointer data)
+{
+gchar *debug;
+GError *err;
+
+switch (GST_MESSAGE_TYPE (msg)) {
+       case GST_MESSAGE_EOS:
+       g_print ("EOS\n");
+               speaking=FALSE;
+       break;
+       case GST_MESSAGE_ERROR:
+               gst_message_parse_error (msg, &err, &debug);
+               g_free (debug);
+
+               g_printf ("Error: %s\n", err->message);
+               g_error_free (err);
+
+               speaking=FALSE;
+       break;
+       case GST_MESSAGE_STATE_CHANGED:
+
+       break;
+    default:
+               g_print("HUH: %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
+       break;
+       }
+return TRUE;
+}
+
+static gboolean
+speak_create_pipeline(void)
+{
+ge.pipeline=gst_pipeline_new("pipeline");
+ge.src=gst_element_factory_make("appsrc", "source");
+ge.caps=gst_element_factory_make("capsfilter", "caps");
+ge.srccaps=gst_caps_new_simple ("audio/x-raw-int",
+                       "depth", G_TYPE_INT, 16,
+                       "signed", G_TYPE_BOOLEAN, TRUE, 
+                       "width", G_TYPE_INT,  16,
+                       "rate", G_TYPE_INT, erate,
+                       "channels", G_TYPE_INT, 1,
+                       NULL);
+
+ge.conv=gst_element_factory_make("audioconverter", "converter");
+ge.queue=gst_element_factory_make("queue", "queue");
+ge.sink=gst_element_factory_make(AUDIO_SINK, "sink");
+
+g_object_set(ge.caps, "caps", ge.srccaps, NULL);
+
+gst_bin_add_many (GST_BIN(ge.pipeline), ge.src, ge.queue, ge.sink, NULL);
+
+if (!gst_element_link_filtered(ge.src, ge.queue, ge.srccaps)) {
+       g_warning ("Failed to link elements 1!");
+       return FALSE;
+}
+
+if (!gst_element_link_filtered(ge.queue, ge.sink, ge.srccaps)) {
+       g_warning ("Failed to link elements 2!");
+       return FALSE;
+}
+
+return TRUE;
+}
+
+static void
+espeak_buffer_free(void *p)
+{
+g_free(p);
+}
+
+static int 
+espeak_cb(short *wav, int numsamples, espeak_EVENT *events)
+{
+GstBuffer *buf;
+gchar *data;
+
+g_print("Adding buffer %d\n", numsamples);
+
+if (wav==NULL) {
+       gst_app_src_end_of_stream (GST_APP_SRC (ge.src));
+       return 0;
+} else if (numsamples>0) {
+       numsamples=numsamples*2;
+       data=g_memdup(wav, numsamples);
+       buf=gst_app_buffer_new (data, numsamples, espeak_buffer_free, data);
+       gst_buffer_set_caps(buf, ge.srccaps);
+       gst_app_src_push_buffer (GST_APP_SRC (ge.src), buf);
+}
+
+return 0;
+}
+
+gboolean
+speak_init(void)
+{
+erate=espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, 1000, NULL, 0);
+if (erate==-1) 
+       return FALSE;
+
+espeak_SetSynthCallback(espeak_cb);
+espeak_SetVoiceByName("en");
+espeak_SetParameter(espeakRATE,140,0);
+espeak_SetParameter(espeakVOLUME,100,0);
+if (speak_create_pipeline()==FALSE)
+       return FALSE;
+
+bus = gst_pipeline_get_bus (GST_PIPELINE (ge.pipeline));
+gst_bus_add_watch (bus, bus_call, NULL);
+
+return TRUE;
+}
+
+void
+speak_deinit(void)
+{
+gst_element_set_state (ge.pipeline, GST_STATE_NULL);
+gst_object_unref (ge.pipeline);
+ge.pipeline=NULL;
+speaking=FALSE;
+}
+
+gboolean
+speak_text(gchar *text)
+{
+#if 0
+if (speaking==TRUE)
+       return FALSE;
+#endif
+g_printf("Speaking: %s (%d)\n", text, strlen(text));
+espeak_Synth(text, strlen(text)+1, 0, POS_CHARACTER, 0, espeakCHARS_8BIT, NULL, NULL);
+
+if (gst_element_set_state (ge.pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+       g_print("Failed to play\n");
+       speaking=FALSE;
+       return FALSE;
+}
+speaking=TRUE;
+g_print("Playing...\n");
+return TRUE;
+}
+
+gboolean
+speak_speaking(void)
+{
+return speaking;
+}
+
+gboolean
+speak_stop(void)
+{
+if (gst_element_set_state(ge.pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE)
+    return FALSE;
+return TRUE;
+}
+
+#else
+
+gboolean speak_init(void) {return TRUE;}
+void speak_deinit(void) {}
+gboolean speak_stop(void) {return TRUE;}
+gboolean speak_speaking(void) {return FALSE;}
+
+gboolean 
+speak_text(gchar *text)
+{
+#ifdef WITH_ESPEAK
+#define _voice_synth_path "/usr/bin/espeak"
+#else
+#define _voice_synth_path "/usr/bin/flite"
+#endif
+
+if (!fork()) {
+       /* We are the fork child.  Synthesize the voice. */
+       sound_noise();
+       sleep(1);
+       printf("%s %s\n", _voice_synth_path, phrase);
+#ifdef WITH_ESPEAK
+       execl(_voice_synth_path, _voice_synth_path, "-t", text, (char *)NULL);
+#else
+       execl(_voice_synth_path, _voice_synth_path, "-s", "150", text, (char *)NULL);
+#endif
+       exit(0);
+}
+
+return TRUE;
+}
+
+#endif
diff --git a/src/speak.h b/src/speak.h
new file mode 100644 (file)
index 0000000..7bb4b46
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _SPEAK_H
+#define _SPEAK_H
+
+#include <glib.h>
+
+gboolean speak_init(void);
+void speak_deinit(void);
+gboolean speak_stop(void);
+gboolean speak_speaking(void);
+gboolean speak_text(gchar *text);
+
+#endif
index 3f3ee3e1523a4f9e4a99c5e9bc1078e99ebd8b53..0c3f2639fdd6ec790c41afd97f8730b990d39409 100644 (file)
@@ -33,48 +33,6 @@ gdk_beep();
 #endif
 }
 
-void sound_speak(gchar * phrase)
-{
-#ifdef WITH_ESPEAK
-#define _voice_synth_path "/usr/bin/espeak"
-#else
-#define _voice_synth_path "/usr/bin/flite"
-#endif
-
-if (!fork()) {
-       /* We are the fork child.  Synthesize the voice. */
-       sound_noise();
-       sleep(1);
-       printf("%s %s\n", _voice_synth_path, phrase);
-       execl(_voice_synth_path, _voice_synth_path, "-t", phrase, (char *)NULL);
-       exit(0);
-}
-
-}
-
-#if 0
-void latlon2unit(gdouble lat, gdouble lon, gint *unitx_, gint *unity_)
-{
-       gdouble tmp;
-
-       gint unitx = &unitx_;
-       gint unity = &unity_;
-
-       unitx = (lon + 180.f) * (WORLD_SIZE_UNITS / 360.f) + 0.5f;
-       tmp = sinf(lat * (PI / 180.f));
-       unity = 0.5f + (WORLD_SIZE_UNITS / MERCATOR_SPAN)
-           * (logf((1.f + tmp) / (1.f - tmp)) * 0.5f - MERCATOR_TOP);
-}
-
-void unit2latlon(gint unitx, gint unity, gdouble *lat, gdouble *lon)
-{
-       (lon) = ((unitx) * (360.f / WORLD_SIZE_UNITS)) - 180.f;
-       (lat) = (360.f * (atanf(expf(((unity)
-                                     * (MERCATOR_SPAN / WORLD_SIZE_UNITS))
-                                    + MERCATOR_TOP)))) * (1.f / PI) - 90.f;
-}
-#endif
-
 void
 deg_format(DegFormat degformat, gdouble coor, gchar * scoor, gchar neg_char,
           gchar pos_char)