--- /dev/null
+#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
#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)