summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Matthew <jonathan@kaolin.wh9.net>2007-08-23 13:24:33 +0000
committerTim-Philipp Müller <tim@centricular.net>2007-08-23 13:24:33 +0000
commit436a8cce7a794a9d980b05dfdde8bcf9e6e6b9aa (patch)
tree1197341fdc523e9fea5e67c3a3c293172e3e1ff8
parent05eba831bd5bfac3ddb7c22b6feefdcea5ca0c61 (diff)
downloadgst-plugins-bad-436a8cce7a794a9d980b05dfdde8bcf9e6e6b9aa.tar.gz
gst-plugins-bad-436a8cce7a794a9d980b05dfdde8bcf9e6e6b9aa.tar.bz2
gst-plugins-bad-436a8cce7a794a9d980b05dfdde8bcf9e6e6b9aa.zip
Port festival plugin to GStreamer-0.10 (#461377).
Original commit message from CVS: Patch by: Jonathan Matthew <jonathan at kaolin wh9 net> * configure.ac: * gst/festival/Makefile.am: * gst/festival/gstfestival.c: Port festival plugin to GStreamer-0.10 (#461377).
-rw-r--r--ChangeLog9
-rw-r--r--configure.ac9
-rw-r--r--gst/festival/Makefile.am4
-rw-r--r--gst/festival/gstfestival.c170
4 files changed, 131 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog
index 45aceb62..ea37b239 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-08-22 Tim-Philipp Müller <tim at centricular dot net>
+
+ Patch by: Jonathan Matthew <jonathan at kaolin wh9 net>
+
+ * configure.ac:
+ * gst/festival/Makefile.am:
+ * gst/festival/gstfestival.c:
+ Port festival plugin to GStreamer-0.10 (#461377).
+
2007-08-22 Wim Taymans <wim.taymans@gmail.com>
* ext/faad/gstfaad.c: (gst_faad_chain):
diff --git a/configure.ac b/configure.ac
index 1005371e..1982616b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,7 @@ GST_PLUGINS_ALL="\
cdxaparse \
deinterlace \
equalizer \
+ festival \
filter \
flv \
freeze \
@@ -160,6 +161,13 @@ AC_SUBST(LIBM)
dnl *** checks for header files ***
+AC_CHECK_HEADERS([unistd.h], HAVE_UNISTD_H=yes)
+AM_CONDITIONAL(HAVE_UNISTD_H, test "x$HAVE_UNISTD_H" = "xyes")
+
+if test "x$HAVE_UNISTD_H" != "xyes"; then
+ GST_PLUGINS_SELECTED=`echo $GST_PLUGINS_SELECTED | $SED -e s/festival//`
+fi
+
dnl used by ext/dts
AX_CREATE_STDINT_H
@@ -982,6 +990,7 @@ gst/bayer/Makefile
gst/cdxaparse/Makefile
gst/deinterlace/Makefile
gst/equalizer/Makefile
+gst/festival/Makefile
gst/filter/Makefile
gst/flv/Makefile
gst/freeze/Makefile
diff --git a/gst/festival/Makefile.am b/gst/festival/Makefile.am
index d785fbe5..45994420 100644
--- a/gst/festival/Makefile.am
+++ b/gst/festival/Makefile.am
@@ -2,10 +2,10 @@
plugin_LTLIBRARIES = libgstfestival.la
libgstfestival_la_SOURCES = gstfestival.c
-libgstfestival_la_CFLAGS = $(GST_CFLAGS)
+libgstfestival_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
# we use net connection now... perhaps use the lib later
# libgstfestival_la_LIBADD = $(FESTIVAL_LIBS)
-libgstfestival_la_LIBADD =
+libgstfestival_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-0.10
libgstfestival_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstfestival.h
diff --git a/gst/festival/gstfestival.c b/gst/festival/gstfestival.c
index f63e0b73..0d8395c9 100644
--- a/gst/festival/gstfestival.c
+++ b/gst/festival/gstfestival.c
@@ -60,9 +60,26 @@
/* */
/*=======================================================================*/
+/**
+ * SECTION:element-festival
+ *
+ * <refsect2>
+ * <para>
+ * This element connects to a
+ * <ulink url="http://www.festvox.org/festival/index.html">festival</ulink> server
+ * process and uses it to synthesize speech.
+ * </para>
+ * <title>Example pipeline</title>
+ * <programlisting>
+ * echo "hi" | gst-launch fdsrc fd=0 ! festival ! wavparse ! audioconvert ! alsasink
+ * </programlisting>
+ * </refsect2>
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -77,11 +94,14 @@
#include "gstfestival.h"
#include <gst/audio/audio.h>
+GST_DEBUG_CATEGORY_STATIC (festival_debug);
+#define GST_CAT_DEFAULT festival_debug
+
static void gst_festival_base_init (gpointer g_class);
static void gst_festival_class_init (GstFestivalClass * klass);
static void gst_festival_init (GstFestival * festival);
-static void gst_festival_chain (GstPad * pad, GstData * _data);
+static GstFlowReturn gst_festival_chain (GstPad * pad, GstBuffer * buf);
static GstStateChangeReturn gst_festival_change_state (GstElement * element,
GstStateChange transition);
@@ -97,21 +117,17 @@ GST_ELEMENT_DETAILS ("Festival Text-to-Speech synthesizer",
"Wim Taymans <wim.taymans@chello.be>");
static GstStaticPadTemplate sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("festival_sink",
+GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("text/plain")
);
static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("festival_src",
+GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) BYTE_ORDER, "
- "signed = (boolean) TRUE, "
- "width = (int) 16, "
- "depth = (int) 16, " "rate = (int) 16000, " "channels = (int) 1")
+ GST_STATIC_CAPS ("audio/x-wav")
);
/* Festival signals and args */
@@ -161,7 +177,7 @@ gst_festival_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- /* register src pads */
+ /* register pads */
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template_factory));
gst_element_class_add_pad_template (element_class,
@@ -197,73 +213,106 @@ gst_festival_init (GstFestival * festival)
festival->info = festival_default_info ();
}
-static void
-gst_festival_chain (GstPad * pad, GstData * _data)
+static gboolean
+read_response (GstFestival * festival)
{
- GstBuffer *buf = GST_BUFFER (_data);
- gchar *wavefile;
- int filesize;
- FILE *fd;
- char *p;
char ack[4];
+ char *data;
+ int filesize;
+ int fd;
int n;
+ gboolean ret = TRUE;
+
+ fd = festival->info->server_fd;
+ do {
+ for (n = 0; n < 3;)
+ n += read (fd, ack + n, 3 - n);
+ ack[3] = '\0';
+ GST_DEBUG_OBJECT (festival, "got response %s", ack);
+
+ if (strcmp (ack, "WV\n") == 0) {
+ GstBuffer *buffer;
+
+ /* receive a waveform */
+ data = socket_receive_file_to_buff (fd, &filesize);
+ GST_DEBUG_OBJECT (festival, "received %d bytes of waveform data",
+ filesize);
+
+ /* push contents as a buffer */
+ buffer = gst_buffer_new ();
+ GST_BUFFER_SIZE (buffer) = (filesize);
+ GST_BUFFER_DATA (buffer) = (guint8 *) data;
+ GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) data;
+ GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
+
+ gst_pad_push (festival->srcpad, buffer);
+
+ } else if (strcmp (ack, "LP\n") == 0) {
+ /* receive an s-expr */
+ data = client_accept_s_expr (fd);
+ GST_DEBUG_OBJECT (festival, "received s-expression: %s", data);
+ g_free (data);
+ } else if (strcmp (ack, "ER\n") == 0) {
+ /* server got an error */
+ GST_ELEMENT_ERROR (festival,
+ LIBRARY,
+ FAILED,
+ ("Festival speech server returned an error"),
+ ("Make sure you have voices/languages installed"));
+ ret = FALSE;
+ break;
+ }
+
+ } while (strcmp (ack, "OK\n") != 0);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_festival_chain (GstPad * pad, GstBuffer * buf)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
GstFestival *festival;
- GstBuffer *outbuf;
- glong size;
+ guint8 *p, *ep;
+ FILE *fd;
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (buf != NULL);
- g_return_if_fail (GST_BUFFER_DATA (buf) != NULL);
+ festival = GST_FESTIVAL (GST_PAD_PARENT (pad));
- festival = GST_FESTIVAL (gst_pad_get_parent (pad));
- GST_DEBUG ("gst_festival_chain: got buffer in '%s'",
- gst_object_get_name (GST_OBJECT (festival)));
+ GST_LOG_OBJECT (festival, "Got text buffer, %u bytes", GST_BUFFER_SIZE (buf));
fd = fdopen (dup (festival->info->server_fd), "wb");
- size = GST_BUFFER_SIZE (buf);
-
/* Copy text over to server, escaping any quotes */
fprintf (fd, "(Parameter.set 'Audio_Required_Rate 16000)\n");
- fprintf (fd, "(tts_textall \"\n");
- for (p = GST_BUFFER_DATA (buf); p && (*p != '\0') && size; p++, size--) {
- if ((*p == '"') || (*p == '\\'))
+ fflush (fd);
+ GST_DEBUG_OBJECT (festival, "issued Parameter.set command");
+ if (read_response (festival) == FALSE) {
+ ret = GST_FLOW_ERROR;
+ goto out;
+ }
+
+ fprintf (fd, "(tts_textall \"");
+ p = GST_BUFFER_DATA (buf);
+ ep = p + GST_BUFFER_SIZE (buf);
+ for (; p < ep && (*p != '\0'); p++) {
+ if ((*p == '"') || (*p == '\\')) {
putc ('\\', fd);
+ }
+
putc (*p, fd);
}
fprintf (fd, "\" \"%s\")\n", festival->info->text_mode);
fclose (fd);
- /* Read back info from server */
- /* This assumes only one waveform will come back, also LP is unlikely */
- wavefile = NULL;
- do {
- for (n = 0; n < 3;)
- n += read (festival->info->server_fd, ack + n, 3 - n);
- ack[3] = '\0';
- if (strcmp (ack, "WV\n") == 0) /* receive a waveform */
- wavefile =
- socket_receive_file_to_buff (festival->info->server_fd, &filesize);
- else if (strcmp (ack, "LP\n") == 0) /* receive an s-expr */
- client_accept_s_expr (festival->info->server_fd);
- else if (strcmp (ack, "ER\n") == 0) { /* server got an error */
- fprintf (stderr, "festival_client: server returned error\n");
- break;
- }
-
- if (wavefile) {
- outbuf = gst_buffer_new ();
- GST_BUFFER_DATA (outbuf) = wavefile;
- GST_BUFFER_SIZE (outbuf) = filesize;
+ GST_DEBUG_OBJECT (festival, "issued tts_textall command");
- gst_pad_push (festival->srcpad, GST_DATA (outbuf));
-
- wavefile = NULL;
- }
- } while (strcmp (ack, "OK\n") != 0);
+ /* Read back info from server */
+ if (read_response (festival) == FALSE)
+ ret = GST_FLOW_ERROR;
+out:
gst_buffer_unref (buf);
+ return ret;
}
static FT_Info *
@@ -317,7 +366,6 @@ festival_socket_open (const char *host, int port)
return fd;
}
-
static char *
client_accept_s_expr (int fd)
{
@@ -345,17 +393,18 @@ socket_receive_file_to_buff (int fd, int *size)
char c;
bufflen = 1024;
- buff = (char *) malloc (bufflen);
+ buff = (char *) g_malloc (bufflen);
*size = 0;
for (k = 0; file_stuff_key[k] != '\0';) {
n = read (fd, &c, 1);
if (n == 0)
break; /* hit stream eof before end of file */
+
if ((*size) + k + 1 >= bufflen) {
/* +1 so you can add a NULL if you want */
bufflen += bufflen / 4;
- buff = (char *) realloc (buff, bufflen);
+ buff = (char *) g_realloc (buff, bufflen);
}
if (file_stuff_key[k] == c)
k++;
@@ -433,6 +482,9 @@ gst_festival_change_state (GstElement * element, GstStateChange transition)
static gboolean
plugin_init (GstPlugin * plugin)
{
+ GST_DEBUG_CATEGORY_INIT (festival_debug, "festival",
+ 0, "Festival text-to-speech synthesizer");
+
if (!gst_element_register (plugin, "festival", GST_RANK_NONE,
GST_TYPE_FESTIVAL))
return FALSE;