/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * SECTION:element-espeak * * Use espeak as a sound source. * * * Example launch line * |[ * gst-launch-0.10 espeak text="Hello world" ! autoaudiosink * ]| * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "gstespeak.h" #include "espeak.h" GST_DEBUG_CATEGORY_STATIC (gst_espeak_debug); #define GST_CAT_DEFAULT gst_espeak_debug enum { PROP_0, PROP_TEXT, PROP_PITCH, PROP_RATE, PROP_VOICE, PROP_GAP, PROP_TRACK, PROP_VOICES, PROP_CAPS }; static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); static GstFlowReturn gst_espeak_create (GstBaseSrc *, guint64, guint, GstBuffer **); static gboolean gst_espeak_start (GstBaseSrc *); static gboolean gst_espeak_stop (GstBaseSrc *); static gboolean gst_espeak_is_seekable (GstBaseSrc *); static void gst_espeak_init_uri (GType); static void gst_espeak_finalize (GObject *); static void gst_espeak_set_property (GObject *, guint, const GValue *, GParamSpec *); static void gst_espeak_get_property (GObject *, guint, GValue *, GParamSpec *); static GstCaps *gst_espeak_getcaps (GstBaseSrc *); GST_BOILERPLATE_FULL (GstEspeak, gst_espeak, GstBaseSrc, GST_TYPE_BASE_SRC, gst_espeak_init_uri); /******************************************************************************/ static void gst_espeak_base_init (gpointer gclass) { GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); static GstElementDetails details = { "Espeak", "Source", "Uses eSpeak library as a sound source for GStreamer", "Aleksey S. Lim " }; gst_element_class_set_details (element_class, &details); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); } /* initialize the espeak's class */ static void gst_espeak_class_init (GstEspeakClass * klass) { GObjectClass *gobject_class = (GObjectClass *) klass; GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass; basesrc_class->create = gst_espeak_create; basesrc_class->start = gst_espeak_start; basesrc_class->stop = gst_espeak_stop; basesrc_class->is_seekable = gst_espeak_is_seekable; basesrc_class->get_caps = gst_espeak_getcaps; gobject_class->finalize = gst_espeak_finalize; gobject_class->set_property = gst_espeak_set_property; gobject_class->get_property = gst_espeak_get_property; g_object_class_install_property (gobject_class, PROP_TEXT, g_param_spec_string ("text", "Text", "Text to pronounce", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_PITCH, g_param_spec_int ("pitch", "Pitch adjustment", "Pitch adjustment", -100, 100, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_RATE, g_param_spec_int ("rate", "Speed in words per minute", "Speed in words per minute", -100, 100, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_VOICE, g_param_spec_string ("voice", "Current voice", "Current voice", ESPEAK_DEFAULT_VOICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_GAP, g_param_spec_uint ("gap", "Gap", "Word gap", 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_TRACK, g_param_spec_uint ("track", "Track", "Track espeak events", 0, G_MAXINT, ESPEAK_TRACK_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_VOICES, g_param_spec_boxed ("voices", "List of voices", "List of voices", G_TYPE_VALUE_ARRAY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_CAPS, g_param_spec_boxed ("caps", "Caps", "Caps describing the format of the data", GST_TYPE_CAPS, G_PARAM_READABLE)); } /* initialize the new element * instantiate pads and add them to element * set pad calback functions * initialize instance structure */ static void gst_espeak_init (GstEspeak * self, GstEspeakClass * gclass) { self->text = NULL; self->pitch = 0; self->rate = 0; self->voice = g_strdup (ESPEAK_DEFAULT_VOICE); self->voices = espeak_get_voices (); self->speak = espeak_new (GST_ELEMENT (self)); self->caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, espeak_get_sample_rate (), "channels", G_TYPE_INT, 1, "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL); gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_DEFAULT); } static void gst_espeak_finalize (GObject * self_) { GstEspeak *self = GST_ESPEAK (self_); g_free (self->text); self->text = NULL; gst_caps_unref (self->caps); self->caps = NULL; espeak_unref (self->speak); self->speak = NULL; g_free (self->voice); self->voice = NULL; g_value_array_free (self->voices); self->voices = NULL; G_OBJECT_CLASS (parent_class)->dispose (self_); } /******************************************************************************/ static void gst_espeak_set_text (GstEspeak * self, const gchar * text) { g_free (self->text); self->text = g_strdup (text); } static void gst_espeak_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstEspeak *self = GST_ESPEAK (object); switch (prop_id) { case PROP_TEXT: gst_espeak_set_text (self, g_value_get_string (value)); break; case PROP_PITCH: self->pitch = g_value_get_int (value); espeak_set_pitch (self->speak, self->pitch); break; case PROP_RATE: self->rate = g_value_get_int (value); espeak_set_rate (self->speak, self->rate); break; case PROP_VOICE: self->voice = g_strdup (g_value_get_string (value)); espeak_set_voice (self->speak, self->voice); break; case PROP_GAP: self->gap = g_value_get_uint (value); espeak_set_gap (self->speak, self->gap); break; case PROP_TRACK: self->track = g_value_get_uint (value); espeak_set_track (self->speak, self->track); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gst_espeak_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstEspeak *self = GST_ESPEAK (object); switch (prop_id) { case PROP_TEXT: g_value_set_string (value, self->text); break; case PROP_PITCH: g_value_set_uint (value, self->pitch); break; case PROP_RATE: g_value_set_uint (value, self->rate); break; case PROP_VOICE: g_value_set_string (value, self->voice); break; case PROP_GAP: g_value_set_uint (value, self->gap); break; case PROP_TRACK: g_value_set_uint (value, self->track); break; case PROP_VOICES: g_value_set_boxed (value, self->voices); break; case PROP_CAPS: gst_value_set_caps (value, self->caps); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /******************************************************************************/ static GstFlowReturn gst_espeak_create (GstBaseSrc * self_, guint64 offset, guint size, GstBuffer ** buf) { GstEspeak *self = GST_ESPEAK (self_); *buf = espeak_out (self->speak, size); if (*buf) { gst_buffer_set_caps (*buf, self->caps); return GST_FLOW_OK; } else return GST_FLOW_UNEXPECTED; } static gboolean gst_espeak_start (GstBaseSrc * self_) { GST_DEBUG ("gst_espeak_start"); GstEspeak *self = GST_ESPEAK (self_); espeak_in (self->speak, self->text); return TRUE; } static gboolean gst_espeak_stop (GstBaseSrc * self_) { GST_DEBUG ("gst_espeak_stop"); GstEspeak *self = GST_ESPEAK (self_); espeak_reset (self->speak); return TRUE; } static gboolean gst_espeak_is_seekable (GstBaseSrc * src) { return FALSE; } static GstCaps *gst_espeak_getcaps (GstBaseSrc * self_) { GstEspeak *self = GST_ESPEAK (self_); return gst_caps_ref (self->caps); } /******************************************************************************/ static GstURIType gst_espeak_uri_get_type (void) { return GST_URI_SRC; } static gchar **gst_espeak_uri_get_protocols (void) { static gchar *protocols[] = { "espeak", NULL }; return protocols; } static gboolean gst_espeak_uri_set_uri (GstURIHandler * handler, const gchar * uri) { gchar *protocol, *text; gboolean ret; protocol = gst_uri_get_protocol (uri); ret = strcmp (protocol, "espeak") == 0; g_free (protocol); if (!ret) return FALSE; text = gst_uri_get_location (uri); if (!text) return FALSE; gst_espeak_set_text (GST_ESPEAK (handler), text); g_free (text); return TRUE; } static void gst_espeak_uri_handler_init (gpointer g_iface, gpointer iface_data) { GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; iface->get_type = gst_espeak_uri_get_type; iface->get_protocols = gst_espeak_uri_get_protocols; iface->set_uri = gst_espeak_uri_set_uri; } static void gst_espeak_init_uri (GType filesrc_type) { static const GInterfaceInfo urihandler_info = { gst_espeak_uri_handler_init, NULL, NULL }; g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, &urihandler_info); } /******************************************************************************/ /* entry point to initialize the plug-in * initialize the plug-in itself * register the element factories and other features */ static gboolean espeak_init (GstPlugin * espeak) { /* debug category for fltering log messages * * exchange the string 'Template espeak' with your description */ GST_DEBUG_CATEGORY_INIT (gst_espeak_debug, "espeak", 0, "Template espeak"); return gst_element_register (espeak, "espeak", GST_RANK_NONE, GST_TYPE_ESPEAK); } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "espeak", "Uses eSpeak library as a sound source for GStreamer", espeak_init, PACKAGE_VERSION, "LGPL", PACKAGE_NAME, "http://sugarlabs.org/go/DevelopmentTeam/gst-plugins-espeak")