diff options
author | Aleksey Lim <alsroot@member.fsf.org> | 2009-02-05 08:16:49 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@member.fsf.org> | 2009-02-05 08:16:49 (GMT) |
commit | c1cf739f24db8b87efcff613a253cc19cc5918d3 (patch) | |
tree | 20525aec832a2c34f92d82a1cc0f6e73630ba359 | |
parent | e493948ac25d425719ad70d45bb02aefc3e32e06 (diff) |
Add espeak:// uri type and "text" property
-rw-r--r-- | src/gstespeak.c | 290 | ||||
-rw-r--r-- | src/gstespeak.h | 10 |
2 files changed, 209 insertions, 91 deletions
diff --git a/src/gstespeak.c b/src/gstespeak.c index ea69f1d..cd357a1 100644 --- a/src/gstespeak.c +++ b/src/gstespeak.c @@ -61,6 +61,7 @@ #endif #include <gst/gst.h> +#include <string.h> #include "gstespeak.h" #include "espeak.h" @@ -71,6 +72,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_espeak_debug); enum { PROP_0, + PROP_TEXT, PROP_SILENT }; @@ -81,26 +83,27 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ( GST_STATIC_CAPS ("ANY") ); -GST_BOILERPLATE (GstEspeak, gst_espeak, GstBaseSrc, GST_TYPE_BASE_SRC); - -static GstFlowReturn gst_espeak_src_create (GstBaseSrc*, +static GstFlowReturn gst_espeak_create (GstBaseSrc*, guint64, guint, GstBuffer**); -static gboolean gst_espeak_src_start (GstBaseSrc*); -static gboolean gst_espeak_src_stop (GstBaseSrc*); -static gboolean gst_espeak_src_is_seekable (GstBaseSrc*); -static gboolean gst_espeak_src_unlock (GstBaseSrc*); -static gboolean gst_espeak_src_unlock_stop (GstBaseSrc*); -static gboolean gst_espeak_src_do_seek (GstBaseSrc*, GstSegment*); -static gboolean gst_espeak_src_check_get_range (GstBaseSrc*); -static gboolean gst_espeak_src_do_get_size (GstBaseSrc*, guint64*); - -static void gst_espeak_src_dispose (GObject * gobject); +static gboolean gst_espeak_start (GstBaseSrc*); +static gboolean gst_espeak_stop (GstBaseSrc*); +static gboolean gst_espeak_is_seekable (GstBaseSrc*); +static gboolean gst_espeak_unlock (GstBaseSrc*); +static gboolean gst_espeak_unlock_stop (GstBaseSrc*); +static gboolean gst_espeak_do_seek (GstBaseSrc*, GstSegment*); +static gboolean gst_espeak_check_get_range (GstBaseSrc*); +static gboolean gst_espeak_do_get_size (GstBaseSrc*, guint64*); +static void gst_espeak_init_uri(GType); +static void gst_espeak_finalize(GObject * gobject); static void gst_espeak_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_espeak_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -/* GObject vmethod implementations */ +GST_BOILERPLATE_FULL(GstEspeak, gst_espeak, GstBaseSrc, GST_TYPE_BASE_SRC, + gst_espeak_init_uri); + +/******************************************************************************/ static void gst_espeak_base_init (gpointer gclass) @@ -124,24 +127,29 @@ gst_espeak_class_init (GstEspeakClass * klass) GObjectClass *gobject_class = (GObjectClass *) klass; GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass; - basesrc_class->create = gst_espeak_src_create; - basesrc_class->start = gst_espeak_src_start; - basesrc_class->stop = gst_espeak_src_stop; - basesrc_class->stop = gst_espeak_src_stop; - basesrc_class->is_seekable = gst_espeak_src_is_seekable; - basesrc_class->unlock = gst_espeak_src_unlock; - basesrc_class->unlock_stop = gst_espeak_src_unlock_stop; - basesrc_class->do_seek = gst_espeak_src_do_seek; - basesrc_class->check_get_range = gst_espeak_src_check_get_range; - basesrc_class->get_size = gst_espeak_src_do_get_size; - - gobject_class->dispose = gst_espeak_src_dispose; + basesrc_class->create = gst_espeak_create; + basesrc_class->start = gst_espeak_start; + basesrc_class->stop = gst_espeak_stop; + basesrc_class->stop = gst_espeak_stop; + basesrc_class->is_seekable = gst_espeak_is_seekable; + basesrc_class->unlock = gst_espeak_unlock; + basesrc_class->unlock_stop = gst_espeak_unlock_stop; + basesrc_class->do_seek = gst_espeak_do_seek; + basesrc_class->check_get_range = gst_espeak_check_get_range; + basesrc_class->get_size = gst_espeak_do_get_size; + + 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_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE)); + g_param_spec_boolean("silent", "Silent", + "Produce verbose output ?", + FALSE, G_PARAM_READWRITE)); } /* initialize the new element @@ -153,75 +161,100 @@ static void gst_espeak_init (GstEspeak * self, GstEspeakClass * gclass) { + self->text = NULL; + self->uri = NULL; self->speak = espeak_new(); } static void -gst_espeak_src_dispose(GObject * self_) +gst_espeak_finalize(GObject * self_) { GstEspeak *self = (GstEspeak*)self_; - espeak_unref(self->speak); - self->speak = NULL; + + espeak_unref(self->speak); self->speak = NULL; + g_free(self->text); self->text = NULL; + g_free(self->uri); self->uri = NULL; G_OBJECT_CLASS(parent_class)->dispose(self_); } +/******************************************************************************/ + +static gboolean +gst_espeak_set_text(GstEspeak *self, const gchar *text) +{ + GstState state; + + /* the element must be stopped in order to do this */ + GST_OBJECT_LOCK(self); + state = GST_STATE(self); + GST_OBJECT_UNLOCK (self); + + if (state != GST_STATE_READY && state != GST_STATE_NULL) + { + GST_DEBUG_OBJECT(self, "setting text in wrong state"); + return FALSE; + } + + g_free(self->text); + g_free(self->uri); + + if (text == NULL) { + self->text = NULL; + self->uri = NULL; + } else { + self->text = g_strdup(text); + self->uri = gst_uri_construct ("espeak", self->text); + } + + g_object_notify(G_OBJECT (self), "text"); + gst_uri_handler_new_uri(GST_URI_HANDLER(self), self->uri); + + return TRUE; +} + static void -gst_espeak_set_property (GObject * object, guint prop_id, +gst_espeak_set_property (GObject *object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstEspeak *filter = GST_ESPEAK (object); - - switch (prop_id) { - case PROP_SILENT: - filter->silent = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + GstEspeak *self = GST_ESPEAK(object); + + switch (prop_id) { + case PROP_TEXT: + gst_espeak_set_text(self, g_value_get_string(value)); + break; + case PROP_SILENT: + self->silent = g_value_get_boolean (value); + 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 *filter = GST_ESPEAK (object); - - switch (prop_id) { - case PROP_SILENT: - g_value_set_boolean (value, filter->silent); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* GstElement vmethod implementations */ - -/* 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); + GstEspeak *self = GST_ESPEAK(object); + + switch (prop_id) { + case PROP_TEXT: + g_value_set_string(value, self->text); + break; + case PROP_SILENT: + g_value_set_boolean (value, self->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } /******************************************************************************/ static GstFlowReturn -gst_espeak_src_create (GstBaseSrc * self_, guint64 offset, guint size, +gst_espeak_create (GstBaseSrc * self_, guint64 offset, guint size, GstBuffer ** buf) { GstEspeak *self = (GstEspeak*)self_; @@ -232,51 +265,49 @@ gst_espeak_src_create (GstBaseSrc * self_, guint64 offset, guint size, } static gboolean -gst_espeak_src_start (GstBaseSrc * self_) +gst_espeak_start (GstBaseSrc * self_) { - GstEspeak *self = (GstEspeak*)self_; - GstState status; - gst_element_get_state((GstElement*)self, NULL, &status, 0); + GstEspeak *self = GST_ESPEAK(self_); - if (status == GST_STATE_PAUSED) - return espeak_say(self->speak, "Aa"); + if (self->text == NULL || self->text[0] == 0) + return FALSE; - return TRUE; + return espeak_say(self->speak, self->text); } static gboolean -gst_espeak_src_stop (GstBaseSrc * self) +gst_espeak_stop (GstBaseSrc * self) { return TRUE; } static gboolean -gst_espeak_src_is_seekable (GstBaseSrc * src) +gst_espeak_is_seekable (GstBaseSrc * src) { return FALSE; } -static gboolean gst_espeak_src_unlock (GstBaseSrc * bsrc) +static gboolean gst_espeak_unlock (GstBaseSrc * bsrc) { return TRUE; } -static gboolean gst_espeak_src_unlock_stop (GstBaseSrc * bsrc) +static gboolean gst_espeak_unlock_stop (GstBaseSrc * bsrc) { return TRUE; } -static gboolean gst_espeak_src_do_seek (GstBaseSrc * src, GstSegment * segment) +static gboolean gst_espeak_do_seek (GstBaseSrc * src, GstSegment * segment) { return TRUE; } -static gboolean gst_espeak_src_check_get_range (GstBaseSrc * src) +static gboolean gst_espeak_check_get_range (GstBaseSrc * src) { return FALSE; } -static gboolean gst_espeak_src_do_get_size (GstBaseSrc * src, guint64 * size) +static gboolean gst_espeak_do_get_size (GstBaseSrc * src, guint64 * size) { *size = -1; return TRUE; @@ -284,6 +315,91 @@ static gboolean gst_espeak_src_do_get_size (GstBaseSrc * src, guint64 * size) /******************************************************************************/ +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 const gchar * +gst_espeak_uri_get_uri(GstURIHandler *handler) +{ + GstEspeak *self = GST_ESPEAK(handler); + return self->uri; +} + +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; + + ret = gst_espeak_set_text(GST_ESPEAK(handler), text); + g_free (text); + + return ret; +} + +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->get_uri = gst_espeak_uri_get_uri; + 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); +} + /* gstreamer looks for this structure to register espeaks * * exchange the string 'Template espeak' with your espeak description diff --git a/src/gstespeak.h b/src/gstespeak.h index 90d3044..f7f2884 100644 --- a/src/gstespeak.h +++ b/src/gstespeak.h @@ -69,14 +69,16 @@ struct Espeak; struct _GstEspeak { - GstAudioSrc parent; - struct Espeak *speak; - gboolean silent; + GstAudioSrc parent; + struct Espeak *speak; + gchar *text; + gchar *uri; + gboolean silent; }; struct _GstEspeakClass { - GstAudioSrcClass parent_class; + GstAudioSrcClass parent_class; }; GType gst_espeak_get_type (void); |