-#include "config.h"
+/*
+ * This file is part of mapper
+ *
+ * Copyright (C) 2007 Kaj-Michael Lang
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
-#if defined (WITH_GST) && defined (WITH_ESPEAK)
+#include "config.h"
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
+
+#if defined (WITH_GST) && defined (WITH_ESPEAK)
+
#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 "audio.h"
#include "speak.h"
typedef struct _gst_espeak gst_espeak;
GstElement *pipeline;
GstElement *src;
GstElement *queue;
- GstElement *caps;
- GstElement *conv;
GstElement *sink;
gboolean done;
gshort *buffer;
static gint erate;
static GstBus *bus;
static gboolean speaking=FALSE;
+static gboolean speak_ok;
+static gboolean espeak_ok;
static gboolean
bus_call (GstBus *bus, GstMessage *msg, gpointer data)
case GST_MESSAGE_EOS:
g_print ("EOS\n");
speaking=FALSE;
+ speak_ok=TRUE;
speak_stop();
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug);
g_free (debug);
- g_printf ("Error: %s\n", err->message);
+ g_debug("Error: %s", err->message);
g_error_free (err);
speak_stop();
speaking=FALSE;
+ speak_ok=FALSE;
break;
case GST_MESSAGE_STATE_CHANGED:
-
+ g_debug("GST: state changed");
break;
default:
- g_print("HUH: %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
+ g_debug("GST: %s", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
break;
}
return TRUE;
speak_create_pipeline(void)
{
ge.pipeline=gst_pipeline_new("pipeline");
+g_assert(ge.pipeline);
+
ge.src=gst_element_factory_make("appsrc", "source");
-ge.caps=gst_element_factory_make("capsfilter", "caps");
+g_assert(ge.src);
+
ge.srccaps=gst_caps_new_simple ("audio/x-raw-int",
"depth", G_TYPE_INT, 16,
"signed", G_TYPE_BOOLEAN, TRUE,
"rate", G_TYPE_INT, erate,
"channels", G_TYPE_INT, 1,
NULL);
+g_assert(ge.srccaps);
-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_assert(ge.queue);
-g_object_set(ge.caps, "caps", ge.srccaps, NULL);
+ge.sink=gst_element_factory_make(AUDIO_SINK, "sink");
+g_assert(ge.sink);
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!");
+ g_warning ("Failed to link source to queue with caps.");
return FALSE;
}
+gst_caps_unref(ge.srccaps);
-if (!gst_element_link_filtered(ge.queue, ge.sink, ge.srccaps)) {
- g_warning ("Failed to link elements 2!");
+if (!gst_element_link(ge.queue, ge.sink)) {
+ g_warning ("Failed to link queue to sink.");
return FALSE;
}
static void
espeak_buffer_free(void *p)
{
-g_print("Buffer free\n");
g_free(p);
}
g_print("Adding buffer %d\n", numsamples);
if (wav==NULL) {
- gst_app_src_end_of_stream (GST_APP_SRC (ge.src));
+ 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);
+ 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);
+ gst_app_src_push_buffer(GST_APP_SRC (ge.src), buf);
}
return 0;
}
+void
+speak_set_parameters(guint speed, guint pitch)
+{
+espeak_SetParameter(espeakRATE, speed, 0);
+espeak_SetParameter(espeakPITCH, pitch, 0);
+}
+
gboolean
-speak_init(void)
+speak_init(gchar *voice, guint speed, guint pitch)
{
-erate=espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, 1000, NULL, 0);
-if (erate==-1)
+espeak_ok=FALSE;
+erate=espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, 100, NULL, 0);
+if (erate==-1)
return FALSE;
espeak_SetSynthCallback(espeak_cb);
-espeak_SetVoiceByName("en");
-espeak_SetParameter(espeakRATE,140,0);
-espeak_SetParameter(espeakVOLUME,100,0);
+espeak_SetVoiceByName(voice);
+speak_set_parameters(speed, pitch);
+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);
+bus=gst_pipeline_get_bus(GST_PIPELINE (ge.pipeline));
+g_assert(bus);
+gst_bus_add_watch(bus, bus_call, NULL);
+espeak_ok=TRUE;
return TRUE;
}
void
speak_deinit(void)
{
-gst_element_set_state (ge.pipeline, GST_STATE_NULL);
-gst_object_unref (ge.pipeline);
+if (espeak_ok==FALSE)
+ return;
+
+gst_element_set_state(ge.pipeline, GST_STATE_NULL);
+gst_object_unref(ge.pipeline);
ge.pipeline=NULL;
speaking=FALSE;
+espeak_Terminate();
}
gboolean
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;
+g_debug("Speaking: %s (%d)\n", text, strlen(text));
+espeak_Synth(text, strlen(text)+1, 0, POS_CHARACTER, 0, espeakCHARS_UTF8, NULL, NULL);
+
+if (speaking!=TRUE) {
+ 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;
}
-speaking=TRUE;
g_print("Playing...\n");
return TRUE;
}
#else
-gboolean speak_init(void) {return TRUE;}
+gboolean speak_init(gchar voice, guint speed, guint pitch) {return TRUE;}
void speak_deinit(void) {}
gboolean speak_stop(void) {return TRUE;}
gboolean speak_speaking(void) {return FALSE;}
+void speak_set_parameters(guint speed, guint pitch) {}
gboolean
speak_text(gchar *text)
/* We are the fork child. Synthesize the voice. */
sound_noise();
sleep(1);
- printf("%s %s\n", _voice_synth_path, phrase);
+ g_debug("%s %s\n", _voice_synth_path, text);
#ifdef WITH_ESPEAK
execl(_voice_synth_path, _voice_synth_path, "-t", text, (char *)NULL);
#else