diff --git a/ChangeLog b/ChangeLog index 3b2eb2c5be..8c7bb8900b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2004-12-13 Thomas Vander Stichele + + * Makefile.am: + * check/Makefile.am: + * check/gst/.cvsignore: + * check/gst/gstobject.c: + * configure.ac: + adding unit testing + * docs/upload.mak: + fixing double vars + * gst/Makefile.am: + disable some unused stuff + * gst/gstbus.h: + * gst/gsttypes.h: + move typedefs for gstbus + * gst/gstelement.c: + * gst/gstelement.h: + add getter/setter for bus and scheduler + add functionality to have (non-fatal) warnings as messages + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + rework API to be more general for warnings as well + * gst/gstobject.c: + fix docs + * tools/gst-launch.c: + fix macros for errors + 2004-12-13 Wim Taymans * docs/design/part-MT-refcounting.txt: diff --git a/Makefile.am b/Makefile.am index 6b07b00001..2e3bdb7869 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,8 +11,14 @@ if BUILD_TESTS ## SUBDIRS_TESTS = tests testsuite ## FIXME: write tests from scratch SUBDIRS_TESTS = +if HAVE_CHECK +SUBDIRS_CHECK = check +else +SUBDIRS_CHECK = +endif else SUBDIRS_TESTS = +SUBDIRS_CHECK = endif if BUILD_EXAMPLES @@ -35,7 +41,9 @@ aclocal_DATA = gst-element-check-@GST_MAJORMINOR@.m4 SUBDIRS = \ include gst libs tools \ - $(SUBDIRS_TESTS) $(SUBDIRS_EXAMPLES) \ + $(SUBDIRS_CHECK) \ + $(SUBDIRS_TESTS) \ + $(SUBDIRS_EXAMPLES) \ pkgconfig po \ common \ $(SUBDIRS_DOCS) @@ -44,6 +52,7 @@ SUBDIRS = \ DIST_SUBDIRS = \ include libs gst \ tools \ + check \ tests testsuite \ examples \ pkgconfig \ diff --git a/check/Makefile.am b/check/Makefile.am new file mode 100644 index 0000000000..54493ef8e6 --- /dev/null +++ b/check/Makefile.am @@ -0,0 +1,4 @@ +TESTS = gst / gstobject check_PROGRAMS = $ (TESTS) + + AM_CFLAGS = $ (GST_OBJ_CFLAGS) $ (CHECK_CFLAGS) + LDADD = $ (GST_OBJ_LIBS) $ (CHECK_LIBS) diff --git a/check/gst/.gitignore b/check/gst/.gitignore new file mode 100644 index 0000000000..151b49f251 --- /dev/null +++ b/check/gst/.gitignore @@ -0,0 +1 @@ +gstobject diff --git a/check/gst/gstobject.c b/check/gst/gstobject.c new file mode 100644 index 0000000000..6a9eb985ea --- /dev/null +++ b/check/gst/gstobject.c @@ -0,0 +1,162 @@ +/* GStreamer + * + * unit test for GstObject + * + * Copyright (C) <2004> Thomas Vander Stichele + * + * 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. + */ + +#include +#include +#include + +#include + +#include + +/* + Create a fake subclass + */ +typedef struct _GstFakeObjectClass GstFakeObjectClass; +typedef struct _GstFakeObject GstFakeObject; + +struct _GstFakeObject +{ + GstObject object; +}; + +struct _GstFakeObjectClass +{ + GstObjectClass parent_class; +}; + +GType _gst_fake_object_type = 0; + +//static GstObjectClass *parent_class = NULL; +//static guint gst_fake_object_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_fake_object_get_type (void) +{ + if (!_gst_fake_object_type) { + static const GTypeInfo fake_object_info = { + sizeof (GstFakeObjectClass), + NULL, //gst_fake_object_base_class_init, + NULL, //gst_fake_object_base_class_finalize, + NULL, //(GClassInitFunc) gst_fake_object_class_init, + NULL, + NULL, + sizeof (GstFakeObject), + 0, + NULL, //(GInstanceInitFunc) gst_fake_object_init, + NULL + }; + + _gst_fake_object_type = g_type_register_static (GST_TYPE_OBJECT, + "GstFakeObject", &fake_object_info, 0); + } + return _gst_fake_object_type; +} + +/* g_object_new on abstract GstObject should fail */ +START_TEST (test_fail_abstract_new) +{ + GstObject *object; + + object = g_object_new (gst_object_get_type (), NULL); + /* this should assert and segfault, but we add fallbacks anyway */ + fail_unless (object == NULL, "Created an instance of abstract GstObject"); +} + +END_TEST +/* g_object_new on GstFakeObject should succeed */ +START_TEST (test_fake_object_new) +{ + GstObject *object; + + object = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object == NULL, "Failed to create instance of GstFakeObject"); + fail_unless (GST_IS_OBJECT (object), + "GstFakeObject instance is not a GstObject"); +} + +END_TEST +/* GstFakeObject name tests */ +START_TEST (test_fake_object_name) +{ + GstObject *object; + gchar *name; + gchar *name2; + + object = g_object_new (gst_fake_object_get_type (), NULL); + + name = gst_object_get_name (object); + fail_if (name != NULL, "Newly created object has a name"); + + /* give a random name by setting with NULL; + * GstFakeObject class -> fakeobject%d */ + gst_object_set_name (object, NULL); + name = gst_object_get_name (object); + fail_if (name == NULL, "Random name was not assigned"); + fail_if (strncmp (name, "fakeobject", 10) != 0, + "Random name %s does not start with Gst", name); + g_free (name); + + gst_object_set_name (object, "fake"); + name = gst_object_get_name (object); + fail_if (name == NULL, "Failed to get name of GstFakeObject"); + fail_if (strcmp (name, "fake") != 0, "Name of GstFakeObject is not 'fake'"); + + /* change the gotten name to see that it's a copy and not the original */ + name[0] = 'm'; + name2 = gst_object_get_name (object); + fail_if (strcmp (name2, "fake") != 0, + "Copy of object name affected actual object name"); + g_free (name); + g_free (name2); +} + +END_TEST Suite * +gst_object_suite (void) +{ + Suite *s = suite_create ("GstObject"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test_raise_signal (tc_chain, test_fail_abstract_new, SIGSEGV); + tcase_add_test (tc_chain, test_fake_object_new); + tcase_add_test (tc_chain, test_fake_object_name); + //tcase_add_checked_fixture (tc_chain, setup, teardown); + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = gst_object_suite (); + SRunner *sr = srunner_create (s); + + gst_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +} diff --git a/configure.ac b/configure.ac index 00145d3c0e..2616e443f3 100644 --- a/configure.ac +++ b/configure.ac @@ -313,6 +313,10 @@ AC_SUBST(POPT_LIBS) dnl Check for ucontext.h AC_CHECK_HEADER(ucontext.h, AC_DEFINE(HAVE_UCONTEXT_H, 1, [defined if we have ucontext.h])) +dnl check for "check", unit testing library/header +AM_PATH_CHECK(0.8.2, HAVE_CHECK=yes, HAVE_CHECK=no) +AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_CHECK" = "xyes") + dnl ###################################################################### dnl # Check command line parameters, and set shell variables accordingly # dnl ###################################################################### @@ -669,6 +673,7 @@ libs/gst/control/Makefile libs/gst/dataprotocol/Makefile libs/gst/getbits/Makefile po/Makefile.in +check/Makefile tests/Makefile tests/bufspeed/Makefile tests/instantiate/Makefile diff --git a/docs/upload.mak b/docs/upload.mak index 6bf1e6ec1a..ed01e5e951 100644 --- a/docs/upload.mak +++ b/docs/upload.mak @@ -13,8 +13,6 @@ # correct User entry for the Host entry for the DOC_SERVER # these variables define the location of the online docs -DOC_SERVER=uraeus@freedesktop.org -DOC_BASE=/home/projects/gstreamer/www/data/doc DOC_SERVER=freedesktop.org DOC_BASE=/srv/gstreamer.freedesktop.org/www/data/doc DOC_URL=$(DOC_SERVER):$(DOC_BASE) diff --git a/gst/Makefile.am b/gst/Makefile.am index 75425862d7..c7d3c84521 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -214,13 +214,13 @@ noinst_HEADERS = \ gstarch.h \ cothreads.h -if GST_DISABLE_OMEGA_COTHREADS +#if GST_DISABLE_OMEGA_COTHREADS #libcothreads_la_SOURCES = #libcothreads_la_CFLAGS = -else -libcothreads_la_SOURCES = cothreads.c -libcothreads_la_CFLAGS = $(libgstreamer_@GST_MAJORMINOR@_la_CFLAGS) -endif +#else +#libcothreads_la_SOURCES = cothreads.c +#libcothreads_la_CFLAGS = $(libgstreamer_@GST_MAJORMINOR@_la_CFLAGS) +#endif gstmarshal.h: gstmarshal.list diff --git a/gst/gstbus.h b/gst/gstbus.h index 603913a1f7..3f0545ef7f 100644 --- a/gst/gstbus.h +++ b/gst/gstbus.h @@ -26,7 +26,6 @@ #include G_BEGIN_DECLS - /* --- standard type macros --- */ #define GST_TYPE_BUS (gst_bus_get_type ()) #define GST_BUS(bus) (G_TYPE_CHECK_INSTANCE_CAST ((bus), GST_TYPE_BUS, GstBus)) @@ -35,64 +34,60 @@ G_BEGIN_DECLS #define GST_IS_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_TYPE ((bclass), GST_TYPE_BUS)) #define GST_BUS_GET_CLASS(bus) (G_TYPE_INSTANCE_GET_CLASS ((bus), GST_TYPE_BUS, GstBusClass)) #define GST_BUS_CAST(bus) ((GstBus*)(bus)) - -typedef enum + typedef enum { - GST_BUS_DROP = 0, /* drop message */ - GST_BUS_PASS = 1, /* pass message to async queue */ - GST_BUS_ASYNC = 2, /* pass message to async queue, continue if message is handled */ + GST_BUS_DROP = 0, /* drop message */ + GST_BUS_PASS = 1, /* pass message to async queue */ + GST_BUS_ASYNC = 2, /* pass message to async queue, continue if message is handled */ } GstBusSyncReply; -typedef struct _GstBus GstBus; -typedef struct _GstBusClass GstBusClass; +typedef GstBusSyncReply (*GstBusSyncHandler) (GstBus * bus, + GstMessage * message, gpointer data); +typedef gboolean (*GstBusHandler) (GstBus * bus, GstMessage * message, + gpointer data); -typedef GstBusSyncReply (*GstBusSyncHandler) (GstBus *bus, GstMessage *message, gpointer data); -typedef gboolean (*GstBusHandler) (GstBus *bus, GstMessage *message, gpointer data); +struct _GstBus +{ + GstObject object; -struct _GstBus { - GstObject object; + /*< private > */ + GAsyncQueue *queue; - /*< private >*/ - GAsyncQueue *queue; + GstBusSyncHandler sync_handler; + gpointer sync_handler_data; - GstBusSyncHandler sync_handler; - gpointer sync_handler_data; + gint control_socket[2]; + GIOChannel *io_channel; - gint control_socket[2]; - GIOChannel *io_channel; - - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; -struct _GstBusClass { - GstObjectClass parent_class; +struct _GstBusClass +{ + GstObjectClass parent_class; - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; -GType gst_bus_get_type (void); +GType gst_bus_get_type (void); -gboolean gst_bus_post (GstBus *bus, GstMessage *message); +gboolean gst_bus_post (GstBus * bus, GstMessage * message); -gboolean gst_bus_have_pending (GstBus *bus); -const GstMessage* gst_bus_peek (GstBus *bus); -GstMessage* gst_bus_pop (GstBus *bus); +gboolean gst_bus_have_pending (GstBus * bus); +const GstMessage *gst_bus_peek (GstBus * bus); +GstMessage *gst_bus_pop (GstBus * bus); -void gst_bus_set_sync_handler (GstBus *bus, GstBusSyncHandler func, - gpointer data); +void gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func, + gpointer data); -GSource* gst_bus_create_watch (GstBus *bus); -guint gst_bus_add_watch_full (GstBus *bus, - gint priority, - GstBusHandler handler, - gpointer user_data, - GDestroyNotify notify); -guint gst_bus_add_watch (GstBus *bus, - GstBusHandler handler, - gpointer user_data); +GSource *gst_bus_create_watch (GstBus * bus); +guint gst_bus_add_watch_full (GstBus * bus, + gint priority, + GstBusHandler handler, gpointer user_data, GDestroyNotify notify); +guint gst_bus_add_watch (GstBus * bus, + GstBusHandler handler, gpointer user_data); G_END_DECLS - #endif /* __GST_BUS_H__ */ diff --git a/gst/gstelement.c b/gst/gstelement.c index 7d75a361e1..9e06da25f0 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -69,6 +69,9 @@ static gboolean gst_element_get_state_func (GstElement * element, GstElementState * state, GstElementState * pending, GTimeVal * timeout); static void gst_element_set_manager_func (GstElement * element, GstPipeline * manager); +static void gst_element_set_bus_func (GstElement * element, GstBus * bus); +static void gst_element_set_scheduler_func (GstElement * element, + GstScheduler * scheduler); #ifndef GST_DISABLE_LOADSAVE static xmlNodePtr gst_element_save_thyself (GstObject * object, @@ -143,6 +146,8 @@ gst_element_class_init (GstElementClass * klass) klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state); klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func); klass->set_manager = GST_DEBUG_FUNCPTR (gst_element_set_manager_func); + klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func); + klass->set_scheduler = GST_DEBUG_FUNCPTR (gst_element_set_scheduler_func); klass->numpadtemplates = 0; klass->elementfactory = NULL; @@ -444,6 +449,7 @@ gst_element_add_pad (GstElement * element, GstPad * pad) /* locking pad to look at the name */ GST_LOCK (pad); /* then check to see if there's already a pad by that name here */ + if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, GST_PAD_NAME (pad)))) goto name_exists; @@ -1311,24 +1317,29 @@ gst_element_convert (GstElement * element, gboolean gst_element_post_message (GstElement * element, GstMessage * message) { - GstPipeline *manager; + GstBus *bus; gboolean result = FALSE; + GST_DEBUG ("posting message %p ...", message); + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (message != NULL, FALSE); GST_LOCK (element); - manager = element->manager; - if (manager == NULL) { + bus = element->bus; + + if (bus == NULL) { + GST_DEBUG ("... but I won't because I have no bus"); GST_UNLOCK (element); gst_data_unref (GST_DATA (message)); return FALSE; } - gst_object_ref (GST_OBJECT (manager)); + gst_object_ref (GST_OBJECT (bus)); + GST_DEBUG ("... on bus %p", bus); GST_UNLOCK (element); - result = gst_pipeline_post_message (manager, message); - gst_object_unref (GST_OBJECT (manager)); + result = gst_bus_post (bus, message); + gst_object_unref (GST_OBJECT (bus)); return result; } @@ -1361,77 +1372,79 @@ _gst_element_error_printf (const gchar * format, ...) } /** - * gst_element_error_full: - * @element: a #GstElement with the error. - * @domain: the GStreamer error domain this error belongs to. - * @code: the error code belonging to the domain - * @message: an allocated message to be used as a replacement for the default - * message connected to code, or NULL - * @debug: an allocated debug message to be used as a replacement for the - * default debugging information, or NULL - * @file: the source code file where the error was generated + * gst_element_message_full: + * @element: a #GstElement to send message from + * @type: the #GstMessageType + * @domain: the GStreamer GError domain this message belongs to + * @code: the GError code belonging to the domain + * @text: an allocated text string to be used as a replacement for the + * default message connected to code, or NULL + * @debug: an allocated debug message to be used as a replacement for the + * default debugging information, or NULL + * @file: the source code file where the error was generated * @function: the source code function where the error was generated - * @line: the source code line where the error was generated + * @line: the source code line where the error was generated * - * Signals an error condition on an element. - * This function is used internally by elements. - * It results in the "error" signal. + * Post an error or warning message on the bus from inside an element. * * MT safe. */ -void gst_element_error_full - (GstElement * element, GQuark domain, gint code, gchar * message, +void gst_element_message_full + (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, gchar * debug, const gchar * file, const gchar * function, gint line) { - GError *error = NULL; + GError *gerror = NULL; gchar *name; - gchar *sent_message; + gchar *sent_text; gchar *sent_debug; - gchar *elem_name; + GstMessage *message = NULL; /* checks */ + GST_DEBUG ("start"); g_return_if_fail (GST_IS_ELEMENT (element)); + g_return_if_fail ((type == GST_MESSAGE_ERROR) || + (type == GST_MESSAGE_WARNING)); - elem_name = gst_element_get_name (element); - - /* check if we send the given message or the default error message */ - if ((message == NULL) || (message[0] == 0)) { - /* we got this message from g_strdup_printf (""); */ - g_free (message); - sent_message = gst_error_get_message (domain, code); + /* check if we send the given text or the default error text */ + if ((text == NULL) || (text[0] == 0)) { + /* text could have come from g_strdup_printf (""); */ + g_free (text); + sent_text = gst_error_get_text (domain, code); } else - sent_message = message; + sent_text = text; + /* construct a sent_debug with extra information from source */ if ((debug == NULL) || (debug[0] == 0)) { - /* we got this debug from g_strdup_printf (""); */ - g_free (debug); - debug = NULL; - } - - /* create error message */ - GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signaling error in %s: %s", - elem_name, sent_message); - error = g_error_new_literal (domain, code, sent_message); - - /* emit the signal, make sure the element stays available */ - name = gst_object_get_path_string (GST_OBJECT (element)); - if (debug) + /* debug could have come from g_strdup_printf (""); */ + sent_debug = NULL; + } else { + name = gst_object_get_path_string (GST_OBJECT (element)); sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s", file, line, function, name, debug ? debug : ""); - else - sent_debug = NULL; + g_free (name); + } g_free (debug); - g_free (name); - gst_element_post_message (element, - gst_message_new_error (GST_OBJECT (element), error, sent_debug)); + /* create gerror and post message */ + GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s", + sent_text); + gerror = g_error_new_literal (domain, code, sent_text); - GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signalled error in %s: %s", - elem_name, sent_message); + if (type == GST_MESSAGE_ERROR) { + message = gst_message_new_error (GST_OBJECT (element), gerror, sent_debug); + } else { + message = gst_message_new_warning (GST_OBJECT (element), gerror, + sent_debug); + } + gst_element_post_message (element, message); + + GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted message: %s", + sent_text); /* cleanup */ - g_free (sent_message); - g_free (elem_name); + g_free (sent_text); + /* sent_debug is not part of the gerror, so don't free it here */ } /** @@ -2073,6 +2086,33 @@ gst_element_set_manager_func (GstElement * element, GstPipeline * manager) GST_UNLOCK (element); } +static void +gst_element_set_bus_func (GstElement * element, GstBus * bus) +{ + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus); + + GST_LOCK (element); + gst_object_replace ((GstObject **) & GST_ELEMENT_BUS (element), + GST_OBJECT (bus)); + GST_UNLOCK (element); +} + +static void +gst_element_set_scheduler_func (GstElement * element, GstScheduler * scheduler) +{ + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", + scheduler); + + GST_LOCK (element); + gst_object_replace ((GstObject **) & GST_ELEMENT_SCHEDULER (element), + GST_OBJECT (scheduler)); + GST_UNLOCK (element); +} + /** * gst_element_set_manager: * @element: a #GstElement to set the manager of. @@ -2096,6 +2136,7 @@ gst_element_set_manager (GstElement * element, GstPipeline * manager) oclass->set_manager (element, manager); } + /** * gst_element_get_manager: * @element: a #GstElement to get the manager of. @@ -2121,6 +2162,92 @@ gst_element_get_manager (GstElement * element) return result; } +/** + * gst_element_set_bus: + * @element: a #GstElement to set the bus of. + * @bus: the #GstBus to set. + * + * Sets the bus of the element. For internal use only, unless you're + * testing elements. + */ +void +gst_element_set_bus (GstElement * element, GstBus * bus) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->set_bus) + oclass->set_bus (element, bus); +} + +/** + * gst_element_get_bus: + * @element: a #GstElement to get the bus of. + * + * Returns the bus of the element. + * + * Returns: the element's #GstBus. + */ +GstBus * +gst_element_get_bus (GstElement * element) +{ + GstBus *result = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), result); + + GST_LOCK (element); + result = GST_ELEMENT_BUS (element); + GST_UNLOCK (element); + + return result; +} + +/** + * gst_element_set_scheduler: + * @element: a #GstElement to set the scheduler of. + * @scheduler: the #GstScheduler to set. + * + * Sets the scheduler of the element. For internal use only, unless you're + * testing elements. + */ +void +gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->set_scheduler) + oclass->set_scheduler (element, scheduler); +} + +/** + * gst_element_get_scheduler: + * @element: a #GstElement to get the scheduler of. + * + * Returns the scheduler of the element. + * + * Returns: the element's #GstScheduler. + */ +GstScheduler * +gst_element_get_scheduler (GstElement * element) +{ + GstScheduler *result = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), result); + + GST_LOCK (element); + result = GST_ELEMENT_SCHEDULER (element); + GST_UNLOCK (element); + + return result; +} + /** * gst_element_create_task: * @element: a #GstElement to get the manager of. diff --git a/gst/gstelement.h b/gst/gstelement.h index d92eeb2236..be3f088102 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -34,24 +34,25 @@ #include #include #include +#include #include #include -G_BEGIN_DECLS - -typedef struct _GstElementDetails GstElementDetails; +G_BEGIN_DECLS typedef struct _GstElementDetails GstElementDetails; /* FIXME: need translatable stuff in here (how handle in registry)? */ -struct _GstElementDetails { - /*< public >*/ +struct _GstElementDetails +{ + /*< public > */ gchar *longname; /* long, english name */ gchar *klass; /* type of element, as hierarchy */ gchar *description; /* insights of one form or another */ gchar *author; /* who wrote this thing? */ - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; + #define GST_ELEMENT_DETAILS(longname,klass,description,author) \ { longname, klass, description, author, GST_PADDING_INIT } #define GST_IS_ELEMENT_DETAILS(details) ( \ @@ -102,7 +103,8 @@ GST_EXPORT GType _gst_element_type; GST_EVENT_MASK_FUNCTION (GstElement*, functionname, a); #endif -typedef enum { +typedef enum +{ /* private flags that can be used by the scheduler */ GST_ELEMENT_SCHEDULER_PRIVATE1, GST_ELEMENT_SCHEDULER_PRIVATE2, @@ -111,25 +113,43 @@ typedef enum { GST_ELEMENT_LOCKED_STATE, /* use some padding for future expansion */ - GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16 + GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16 } GstElementFlags; #define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj)) #define GST_ELEMENT_PARENT(obj) (GST_ELEMENT_CAST(GST_OBJECT_PARENT(obj))) #define GST_ELEMENT_MANAGER(obj) (GST_ELEMENT_CAST(obj)->manager) +#define GST_ELEMENT_BUS(obj) (GST_ELEMENT_CAST(obj)->bus) +#define GST_ELEMENT_SCHEDULER(obj) (GST_ELEMENT_CAST(obj)->scheduler) #define GST_ELEMENT_CLOCK(obj) (GST_ELEMENT_CAST(obj)->clock) #define GST_ELEMENT_PADS(obj) (GST_ELEMENT_CAST(obj)->pads) -#define GST_ELEMENT_ERROR(el, domain, code, message, debug) G_STMT_START { \ - gchar *__msg = _gst_element_error_printf message; \ - gchar *__dbg = _gst_element_error_printf debug; \ - if (__msg) \ - GST_ERROR_OBJECT (el, "%s", __msg); \ - if (__dbg) \ - GST_ERROR_OBJECT (el, "%s", __dbg); \ - gst_element_error_full (GST_ELEMENT(el), \ - GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code, \ - __msg, __dbg, __FILE__, GST_FUNCTION, __LINE__); \ +/* log a (fatal) error message and post it on the bus */ +#define GST_ELEMENT_ERROR(el, domain, code, text, debug) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_ERROR_OBJECT (el, "%s", __txt); \ + if (__dbg) \ + GST_ERROR_OBJECT (el, "%s", __dbg); \ + gst_element_message_full (GST_ELEMENT(el), GST_MESSAGE_ERROR, \ + GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code, \ + __txt, __dbg, __FILE__, GST_FUNCTION, __LINE__); \ +} G_STMT_END + +/* log a (non-fatal) warning message and post it on the bus */ +#define GST_ELEMENT_WARNING(el, domain, code, text, debug) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_WARNING_OBJECT (el, "%s", __txt); \ + if (__dbg) \ + GST_WARNING_OBJECT (el, "%s", __dbg); \ + gst_element_message_full (GST_ELEMENT(el), GST_MESSAGE_WARNING, \ + GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code, \ + __txt, __dbg, __FILE__, GST_FUNCTION, __LINE__); \ } G_STMT_END /* the state change mutexes and conds */ @@ -140,116 +160,127 @@ typedef enum { #define GST_STATE_GET_COND(elem) (GST_ELEMENT_CAST(elem)->state_cond) #define GST_STATE_WAIT(elem) g_cond_wait (GST_STATE_GET_COND (elem), GST_STATE_GET_LOCK (elem)) #define GST_STATE_TIMED_WAIT(elem, timeval) g_cond_timed_wait (GST_STATE_GET_COND (elem), GST_STATE_GET_LOCK (elem),\ - timeval) + timeval) typedef struct _GstElementFactory GstElementFactory; typedef struct _GstElementFactoryClass GstElementFactoryClass; -struct _GstElement { - GstObject object; +struct _GstElement +{ + GstObject object; - /*< public >*/ /* with STATE_LOCK */ + /*< public > *//* with STATE_LOCK */ /* element state */ - GMutex *state_lock; - GCond *state_cond; - guint8 current_state; - guint8 pending_state; + GMutex *state_lock; + GCond *state_cond; + guint8 current_state; + guint8 pending_state; - /*< public >*/ /* with LOCK */ + /*< public > *//* with LOCK */ /* element manager */ - GstPipeline *manager; + GstPipeline *manager; + GstBus *bus; + GstScheduler *scheduler; /* private pointer for the scheduler */ - gpointer sched_private; + gpointer sched_private; /* allocated clock */ - GstClock *clock; - GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */ + GstClock *clock; + GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */ /* element pads, these lists can only be iterated while holding * the LOCK or checking the cookie after each LOCK. */ - guint16 numpads; - GList *pads; - guint16 numsrcpads; - GList *srcpads; - guint16 numsinkpads; - GList *sinkpads; - guint32 pads_cookie; + guint16 numpads; + GList *pads; + guint16 numsrcpads; + GList *srcpads; + guint16 numsinkpads; + GList *sinkpads; + guint32 pads_cookie; - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; -struct _GstElementClass { - GstObjectClass parent_class; +struct _GstElementClass +{ + GstObjectClass parent_class; - /*< public >*/ + /*< public > */ /* the element details */ - GstElementDetails details; + GstElementDetails details; /* factory that the element was created from */ - GstElementFactory *elementfactory; + GstElementFactory *elementfactory; /* templates for our pads */ - GList *padtemplates; - gint numpadtemplates; - guint32 pad_templ_cookie; - - /* signal callbacks */ - void (*state_change) (GstElement *element, GstElementState old, GstElementState state); - void (*new_pad) (GstElement *element, GstPad *pad); - void (*pad_removed) (GstElement *element, GstPad *pad); - void (*no_more_pads) (GstElement *element); + GList *padtemplates; + gint numpadtemplates; + guint32 pad_templ_cookie; - /*< protected >*/ + /* signal callbacks */ + void (*state_change) (GstElement * element, GstElementState old, + GstElementState state); + void (*new_pad) (GstElement * element, GstPad * pad); + void (*pad_removed) (GstElement * element, GstPad * pad); + void (*no_more_pads) (GstElement * element); + + /*< protected > */ /* vtable */ /* request/release pads */ - GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar* name); - void (*release_pad) (GstElement *element, GstPad *pad); + GstPad *(*request_new_pad) (GstElement * element, GstPadTemplate * templ, + const gchar * name); + void (*release_pad) (GstElement * element, GstPad * pad); /* state changes */ - gboolean (*get_state) (GstElement *element, GstElementState *state, - GstElementState *pending, GTimeVal *timeout); - GstElementStateReturn (*change_state) (GstElement *element); + gboolean (*get_state) (GstElement * element, GstElementState * state, + GstElementState * pending, GTimeVal * timeout); + GstElementStateReturn (*change_state) (GstElement * element); /* manager */ - void (*set_manager) (GstElement *element, GstPipeline *pipeline); + void (*set_manager) (GstElement * element, GstPipeline * pipeline); + void (*set_bus) (GstElement * element, GstBus * bus); + void (*set_scheduler) (GstElement * element, GstScheduler * scheduler); /* set/get clocks */ - GstClock* (*get_clock) (GstElement *element); - void (*set_clock) (GstElement *element, GstClock *clock); + GstClock *(*get_clock) (GstElement * element); + void (*set_clock) (GstElement * element, GstClock * clock); /* index */ - GstIndex* (*get_index) (GstElement *element); - void (*set_index) (GstElement *element, GstIndex *index); + GstIndex *(*get_index) (GstElement * element); + void (*set_index) (GstElement * element, GstIndex * index); /* query/convert/events functions */ - const GstEventMask* (*get_event_masks) (GstElement *element); - gboolean (*send_event) (GstElement *element, GstEvent *event); - const GstFormat* (*get_formats) (GstElement *element); - gboolean (*convert) (GstElement *element, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); - const GstQueryType* (*get_query_types) (GstElement *element); - gboolean (*query) (GstElement *element, GstQueryType type, - GstFormat *format, gint64 *value); + const GstEventMask *(*get_event_masks) (GstElement * element); + gboolean (*send_event) (GstElement * element, GstEvent * event); + const GstFormat *(*get_formats) (GstElement * element); + gboolean (*convert) (GstElement * element, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); + const GstQueryType *(*get_query_types) (GstElement * element); + gboolean (*query) (GstElement * element, GstQueryType type, + GstFormat * format, gint64 * value); - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING - 1]; }; /* class stuff */ -void gst_element_class_add_pad_template (GstElementClass *klass, GstPadTemplate *templ); -void gst_element_class_install_std_props (GstElementClass *klass, - const gchar *first_name, ...); -void gst_element_class_set_details (GstElementClass *klass, - const GstElementDetails *details); -GstPadTemplate* gst_element_class_get_pad_template (GstElementClass *element_class, const gchar *name); -GList* gst_element_class_get_pad_template_list (GstElementClass *element_class); +void gst_element_class_add_pad_template (GstElementClass * klass, + GstPadTemplate * templ); +void gst_element_class_install_std_props (GstElementClass * klass, + const gchar * first_name, ...); +void gst_element_class_set_details (GstElementClass * klass, + const GstElementDetails * details); +GstPadTemplate *gst_element_class_get_pad_template (GstElementClass * + element_class, const gchar * name); +GList *gst_element_class_get_pad_template_list (GstElementClass * + element_class); /* element instance */ -GType gst_element_get_type (void); +GType gst_element_get_type (void); #define gst_element_get_name(elem) gst_object_get_name(GST_OBJECT(elem)) #define gst_element_set_name(elem,name) gst_object_set_name(GST_OBJECT(elem),name) @@ -257,79 +288,84 @@ GType gst_element_get_type (void); #define gst_element_set_parent(elem,parent) gst_object_set_parent(GST_OBJECT(elem),parent) /* clocking */ -gboolean gst_element_requires_clock (GstElement *element); -gboolean gst_element_provides_clock (GstElement *element); -GstClock* gst_element_get_clock (GstElement *element); -void gst_element_set_clock (GstElement *element, GstClock *clock); +gboolean gst_element_requires_clock (GstElement * element); +gboolean gst_element_provides_clock (GstElement * element); +GstClock *gst_element_get_clock (GstElement * element); +void gst_element_set_clock (GstElement * element, GstClock * clock); -GstClockReturn gst_element_clock_wait (GstElement *element, - GstClockID id, GstClockTimeDiff *jitter); -GstClockTime gst_element_get_time (GstElement *element); -gboolean gst_element_wait (GstElement *element, GstClockTime timestamp); +GstClockReturn gst_element_clock_wait (GstElement * element, + GstClockID id, GstClockTimeDiff * jitter); +GstClockTime gst_element_get_time (GstElement * element); +gboolean gst_element_wait (GstElement * element, GstClockTime timestamp); /* indexes */ -gboolean gst_element_is_indexable (GstElement *element); -void gst_element_set_index (GstElement *element, GstIndex *index); -GstIndex* gst_element_get_index (GstElement *element); +gboolean gst_element_is_indexable (GstElement * element); +void gst_element_set_index (GstElement * element, GstIndex * index); +GstIndex *gst_element_get_index (GstElement * element); /* manager and tasks */ -void gst_element_set_manager (GstElement *element, GstPipeline *pipeline); -GstPipeline* gst_element_get_manager (GstElement *element); -GstTask* gst_element_create_task (GstElement *element, GstTaskFunction func, gpointer data); +void gst_element_set_manager (GstElement * element, GstPipeline * pipeline); +GstPipeline *gst_element_get_manager (GstElement * element); +void gst_element_set_bus (GstElement * element, GstBus * bus); +GstBus *gst_element_get_bus (GstElement * element); +void gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler); +GstScheduler *gst_element_get_scheduler (GstElement * element); +GstTask *gst_element_create_task (GstElement * element, GstTaskFunction func, + gpointer data); /* pad management */ -gboolean gst_element_add_pad (GstElement *element, GstPad *pad); -gboolean gst_element_remove_pad (GstElement *element, GstPad *pad); -GstPad * gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name); -void gst_element_no_more_pads (GstElement *element); +gboolean gst_element_add_pad (GstElement * element, GstPad * pad); +gboolean gst_element_remove_pad (GstElement * element, GstPad * pad); +GstPad *gst_element_add_ghost_pad (GstElement * element, GstPad * pad, + const gchar * name); +void gst_element_no_more_pads (GstElement * element); -GstPad* gst_element_get_pad (GstElement *element, const gchar *name); -GstPad* gst_element_get_static_pad (GstElement *element, const gchar *name); -GstPad* gst_element_get_request_pad (GstElement *element, const gchar *name); -void gst_element_release_request_pad (GstElement *element, GstPad *pad); +GstPad *gst_element_get_pad (GstElement * element, const gchar * name); +GstPad *gst_element_get_static_pad (GstElement * element, const gchar * name); +GstPad *gst_element_get_request_pad (GstElement * element, const gchar * name); +void gst_element_release_request_pad (GstElement * element, GstPad * pad); -GstIterator* gst_element_iterate_pads (GstElement *element); +GstIterator *gst_element_iterate_pads (GstElement * element); /* event/query/format stuff */ -G_CONST_RETURN GstEventMask* - gst_element_get_event_masks (GstElement *element); -gboolean gst_element_send_event (GstElement *element, GstEvent *event); -gboolean gst_element_seek (GstElement *element, GstSeekType seek_type, - guint64 offset); -G_CONST_RETURN GstQueryType* - gst_element_get_query_types (GstElement *element); -gboolean gst_element_query (GstElement *element, GstQueryType type, - GstFormat *format, gint64 *value); -G_CONST_RETURN GstFormat* - gst_element_get_formats (GstElement *element); -gboolean gst_element_convert (GstElement *element, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); +G_CONST_RETURN GstEventMask *gst_element_get_event_masks (GstElement * element); +gboolean gst_element_send_event (GstElement * element, GstEvent * event); +gboolean gst_element_seek (GstElement * element, GstSeekType seek_type, + guint64 offset); +G_CONST_RETURN GstQueryType *gst_element_get_query_types (GstElement * element); +gboolean gst_element_query (GstElement * element, GstQueryType type, + GstFormat * format, gint64 * value); +G_CONST_RETURN GstFormat *gst_element_get_formats (GstElement * element); +gboolean gst_element_convert (GstElement * element, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); /* messages */ -gboolean gst_element_post_message (GstElement *element, GstMessage *message); +gboolean gst_element_post_message (GstElement * element, GstMessage * message); /* error handling */ -gchar * _gst_element_error_printf (const gchar *format, ...); -void gst_element_error_full (GstElement *element, GQuark domain, gint code, - gchar *message, gchar *debug, - const gchar *file, const gchar *function, gint line); +gchar *_gst_element_error_printf (const gchar * format, ...); +void gst_element_message_full (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, gchar * debug, const gchar * file, + const gchar * function, gint line); /* state management */ -gboolean gst_element_is_locked_state (GstElement *element); -gboolean gst_element_set_locked_state (GstElement *element, gboolean locked_state); -gboolean gst_element_sync_state_with_parent (GstElement *element); +gboolean gst_element_is_locked_state (GstElement * element); +gboolean gst_element_set_locked_state (GstElement * element, + gboolean locked_state); +gboolean gst_element_sync_state_with_parent (GstElement * element); -gboolean gst_element_get_state (GstElement *element, GstElementState *state, - GstElementState *pending, GTimeVal *timeout); -GstElementStateReturn gst_element_set_state (GstElement *element, GstElementState state); +gboolean gst_element_get_state (GstElement * element, GstElementState * state, + GstElementState * pending, GTimeVal * timeout); +GstElementStateReturn gst_element_set_state (GstElement * element, + GstElementState state); -void gst_element_abort_state (GstElement *element); -void gst_element_commit_state (GstElement *element); +void gst_element_abort_state (GstElement * element); +void gst_element_commit_state (GstElement * element); /* factory management */ -GstElementFactory* gst_element_get_factory (GstElement *element); +GstElementFactory *gst_element_get_factory (GstElement * element); /* * @@ -345,54 +381,58 @@ GstElementFactory* gst_element_get_factory (GstElement *element); #define GST_IS_ELEMENT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENT_FACTORY)) #define GST_IS_ELEMENT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT_FACTORY)) -struct _GstElementFactory { - GstPluginFeature parent; +struct _GstElementFactory +{ + GstPluginFeature parent; - GType type; /* unique GType of element or 0 if not loaded */ + GType type; /* unique GType of element or 0 if not loaded */ - GstElementDetails details; + GstElementDetails details; - GList * padtemplates; - guint numpadtemplates; + GList *padtemplates; + guint numpadtemplates; /* URI interface stuff */ - guint uri_type; - gchar ** uri_protocols; - - GList * interfaces; /* interfaces this element implements */ + guint uri_type; + gchar **uri_protocols; + + GList *interfaces; /* interfaces this element implements */ gpointer _gst_reserved[GST_PADDING]; }; -struct _GstElementFactoryClass { +struct _GstElementFactoryClass +{ GstPluginFeatureClass parent_class; gpointer _gst_reserved[GST_PADDING]; }; -GType gst_element_factory_get_type (void); +GType gst_element_factory_get_type (void); -gboolean gst_element_register (GstPlugin *plugin, - const gchar *name, - guint rank, - GType type); +gboolean gst_element_register (GstPlugin * plugin, + const gchar * name, guint rank, GType type); -GstElementFactory * gst_element_factory_find (const gchar *name); -GType gst_element_factory_get_element_type (GstElementFactory *factory); -G_CONST_RETURN gchar * gst_element_factory_get_longname (GstElementFactory *factory); -G_CONST_RETURN gchar * gst_element_factory_get_klass (GstElementFactory *factory); -G_CONST_RETURN gchar * gst_element_factory_get_description (GstElementFactory *factory); -G_CONST_RETURN gchar * gst_element_factory_get_author (GstElementFactory *factory); -guint gst_element_factory_get_num_pad_templates (GstElementFactory *factory); -G_CONST_RETURN GList * gst_element_factory_get_pad_templates (GstElementFactory *factory); -guint gst_element_factory_get_uri_type (GstElementFactory *factory); -gchar ** gst_element_factory_get_uri_protocols (GstElementFactory *factory); +GstElementFactory *gst_element_factory_find (const gchar * name); +GType gst_element_factory_get_element_type (GstElementFactory * factory); +G_CONST_RETURN gchar *gst_element_factory_get_longname (GstElementFactory * + factory); +G_CONST_RETURN gchar *gst_element_factory_get_klass (GstElementFactory * + factory); +G_CONST_RETURN gchar *gst_element_factory_get_description (GstElementFactory * + factory); +G_CONST_RETURN gchar *gst_element_factory_get_author (GstElementFactory * + factory); +guint gst_element_factory_get_num_pad_templates (GstElementFactory * factory); +G_CONST_RETURN GList *gst_element_factory_get_pad_templates (GstElementFactory * + factory); +guint gst_element_factory_get_uri_type (GstElementFactory * factory); +gchar **gst_element_factory_get_uri_protocols (GstElementFactory * factory); -GstElement* gst_element_factory_create (GstElementFactory *factory, - const gchar *name); -GstElement* gst_element_factory_make (const gchar *factoryname, const gchar *name); +GstElement *gst_element_factory_create (GstElementFactory * factory, + const gchar * name); +GstElement *gst_element_factory_make (const gchar * factoryname, + const gchar * name); G_END_DECLS - #endif /* __GST_ELEMENT_H__ */ - diff --git a/gst/gsterror.c b/gst/gsterror.c index a8acb6b154..829a2865dc 100644 --- a/gst/gsterror.c +++ b/gst/gsterror.c @@ -28,10 +28,11 @@ #define TABLE(t, d, a, b) t[GST_ ## d ## _ERROR_ ## a] = g_strdup (b) #define QUARK_FUNC(string) \ GQuark gst_ ## string ## _error_quark (void) { \ - static GQuark quark; \ - if (!quark) \ - quark = g_quark_from_static_string ("gst-" # string "-error-quark"); \ - return quark; } + static GQuark q; \ + if (!q) \ + q = g_quark_from_static_string ("gst-" # string "-error-quark"); \ + return q; \ +} GType gst_g_error_get_type (void) @@ -161,29 +162,30 @@ _gst_stream_errors_init (void) return t; } -QUARK_FUNC (core) - QUARK_FUNC (library) - QUARK_FUNC (resource) - QUARK_FUNC (stream) +QUARK_FUNC (core); +QUARK_FUNC (library); +QUARK_FUNC (resource); +QUARK_FUNC (stream); /** - * gst_error_get_message: + * gst_error_get_text: * @domain: the GStreamer error domain this error belongs to. * @code: the error code belonging to the domain. * - * Returns: a newly allocated string describing the error message in the + * Returns: a newly allocated string describing the error text in the * current locale. */ - gchar *gst_error_get_message (GQuark domain, gint code) +gchar * +gst_error_get_text (GQuark domain, gint code) { static gchar **gst_core_errors = NULL; static gchar **gst_library_errors = NULL; static gchar **gst_resource_errors = NULL; static gchar **gst_stream_errors = NULL; - gchar *message = NULL; + gchar *text = NULL; - /* initialize error message tables if necessary */ + /* initialize error text tables if necessary */ if (gst_core_errors == NULL) gst_core_errors = _gst_core_errors_init (); if (gst_library_errors == NULL) @@ -195,23 +197,23 @@ QUARK_FUNC (core) if (domain == GST_CORE_ERROR) - message = gst_core_errors[code]; + text = gst_core_errors[code]; else if (domain == GST_LIBRARY_ERROR) - message = gst_library_errors[code]; + text = gst_library_errors[code]; else if (domain == GST_RESOURCE_ERROR) - message = gst_resource_errors[code]; + text = gst_resource_errors[code]; else if (domain == GST_STREAM_ERROR) - message = gst_stream_errors[code]; + text = gst_stream_errors[code]; else { - g_warning ("No error messages for domain %s", g_quark_to_string (domain)); - return g_strdup_printf (_("No error message for domain %s."), + g_warning ("No error texts for domain %s", g_quark_to_string (domain)); + return g_strdup_printf (_("No error text for domain %s."), g_quark_to_string (domain)); } - if (message) - return g_strdup (_(message)); + if (text) + return g_strdup (_(text)); else return g_strdup_printf (_ - ("No standard error message for domain %s and code %d."), + ("No standard error text for domain %s and code %d."), g_quark_to_string (domain), code); } diff --git a/gst/gsterror.h b/gst/gsterror.h index 9ffac98751..165c00f811 100644 --- a/gst/gsterror.h +++ b/gst/gsterror.h @@ -38,7 +38,7 @@ G_BEGIN_DECLS * the core GStreamer library */ /* FIXME: should we divide in numerical blocks so we can easily add for example PAD errors later ? */ -typedef enum + typedef enum { GST_CORE_ERROR_FAILED = 1, GST_CORE_ERROR_TOO_LAZY, @@ -123,7 +123,7 @@ GstStreamError; #define GST_ERROR_SYSTEM ("system error: %s", g_strerror (errno)) GType gst_g_error_get_type (void); -gchar *gst_error_get_message (GQuark domain, gint code); +gchar *gst_error_get_text (GQuark domain, gint code); GQuark gst_stream_error_quark (void); GQuark gst_core_error_quark (void); GQuark gst_resource_error_quark (void); diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 8bed94a1f0..aeb4a8ac5d 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -102,7 +102,8 @@ _gst_message_free (GstMessage * message) } switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: - g_error_free (GST_MESSAGE_ERROR_ERROR (message)); + case GST_MESSAGE_WARNING: + g_error_free (GST_MESSAGE_ERROR_GERROR (message)); g_free (GST_MESSAGE_ERROR_DEBUG (message)); break; case GST_MESSAGE_TAG: @@ -194,12 +195,31 @@ gst_message_new_error (GstObject * src, GError * error, gchar * debug) GstMessage *message; message = gst_message_new (GST_MESSAGE_ERROR, src); - GST_MESSAGE_ERROR_ERROR (message) = error; + GST_MESSAGE_ERROR_GERROR (message) = error; GST_MESSAGE_ERROR_DEBUG (message) = debug; return message; } +/** + * gst_message_new_warning: + * + * Create a new warning message. + * + * Returns: The new warning message. + */ +GstMessage * +gst_message_new_warning (GstObject * src, GError * error, gchar * debug) +{ + GstMessage *message; + + message = gst_message_new (GST_MESSAGE_WARNING, src); + GST_MESSAGE_WARNING_GERROR (message) = error; + GST_MESSAGE_WARNING_DEBUG (message) = debug; + + return message; +} + /** * gst_message_new_tag: * diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 73eb72ea39..97151ecdef 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -28,20 +28,19 @@ #include #include -G_BEGIN_DECLS +G_BEGIN_DECLS GST_EXPORT GType _gst_message_type; -GST_EXPORT GType _gst_message_type; - -typedef enum { - GST_MESSAGE_UNKNOWN = 0, - GST_MESSAGE_EOS = 1, - GST_MESSAGE_ERROR = 2, - GST_MESSAGE_WARNING = 3, - GST_MESSAGE_INFO = 4, - GST_MESSAGE_TAG = 5, - GST_MESSAGE_BUFFERING = 6, - GST_MESSAGE_STATE_CHANGED = 7, - GST_MESSAGE_STEP_DONE = 8, +typedef enum +{ + GST_MESSAGE_UNKNOWN = 0, + GST_MESSAGE_EOS = 1, + GST_MESSAGE_ERROR = 2, + GST_MESSAGE_WARNING = 3, + GST_MESSAGE_INFO = 4, + GST_MESSAGE_TAG = 5, + GST_MESSAGE_BUFFERING = 6, + GST_MESSAGE_STATE_CHANGED = 7, + GST_MESSAGE_STEP_DONE = 8, } GstMessageType; #define GST_MESSAGE_TRACE_NAME "GstMessage" @@ -56,42 +55,49 @@ typedef enum { #define GST_MESSAGE_TAG_LIST(message) (GST_MESSAGE(message)->message_data.tag.list) -#define GST_MESSAGE_ERROR_ERROR(message) (GST_MESSAGE(message)->message_data.error.error) +#define GST_MESSAGE_ERROR_GERROR(message) (GST_MESSAGE(message)->message_data.error.gerror) #define GST_MESSAGE_ERROR_DEBUG(message) (GST_MESSAGE(message)->message_data.error.debug) +#define GST_MESSAGE_WARNING_GERROR(message) (GST_MESSAGE(message)->message_data.error.gerror) +#define GST_MESSAGE_WARNING_DEBUG(message) (GST_MESSAGE(message)->message_data.error.debug) -struct _GstMessage { +struct _GstMessage +{ GstData data; - /*< public >*/ /* with MESSAGE_LOCK */ - GMutex *lock; /* lock and cond for async delivery */ - GCond *cond; + /*< public > *//* with MESSAGE_LOCK */ + GMutex *lock; /* lock and cond for async delivery */ + GCond *cond; - /*< public >*/ /* with COW */ - GstMessageType type; - guint64 timestamp; - GstObject *src; + /*< public > *//* with COW */ + GstMessageType type; + guint64 timestamp; + GstObject *src; - union { - struct { - GError *error; + union + { + struct + { + GError *gerror; gchar *debug; } error; - struct { - GstStructure *structure; + struct + { + GstStructure *structure; } structure; - struct { - GstTagList *list; + struct + { + GstTagList *list; } tag; } message_data; - /*< private >*/ + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; -void _gst_message_initialize (void); - -GType gst_message_get_type (void); -GstMessage* gst_message_new (GstMessageType type, GstObject *src); +void _gst_message_initialize (void); + +GType gst_message_get_type (void); +GstMessage *gst_message_new (GstMessageType type, GstObject * src); /* refcounting */ #define gst_message_ref(ev) GST_MESSAGE (gst_data_ref (GST_DATA (ev))) @@ -100,10 +106,12 @@ GstMessage* gst_message_new (GstMessageType type, GstObject *src); /* copy message */ #define gst_message_copy(ev) GST_MESSAGE (gst_data_copy (GST_DATA (ev))) -GstMessage* gst_message_new_eos (GstObject *src); -GstMessage* gst_message_new_error (GstObject *src, GError *error, gchar *debug); -GstMessage* gst_message_new_tag (GstObject *src, GstTagList *tag_list); +GstMessage *gst_message_new_eos (GstObject * src); +GstMessage *gst_message_new_error (GstObject * src, GError * error, + gchar * debug); +GstMessage *gst_message_new_warning (GstObject * src, GError * error, + gchar * debug); +GstMessage *gst_message_new_tag (GstObject * src, GstTagList * tag_list); G_END_DECLS - #endif /* __GST_MESSAGE_H__ */ diff --git a/gst/gstobject.c b/gst/gstobject.c index 41baa765fa..d59acaf630 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -604,12 +604,13 @@ gst_object_set_name_default (GstObject * object) /** * gst_object_set_name: - * @object: GstObject to set the name of - * @name: new name of object + * @object: a #GstObject to set the name of + * @name: new name of object * - * Sets the name of the object, or gives the element a guaranteed unique - * name (if @name is NULL). This function makes a copy of the provided - * name so the called must g_free() the name it sent as a parameter. + * Sets the name of the object, or gives the object a guaranteed unique + * name (if @name is NULL). + * This function makes a copy of the provided name, so the caller + * retains ownership of the name it sent. * * MT safe. */ @@ -632,12 +633,14 @@ gst_object_set_name (GstObject * object, const gchar * name) /** * gst_object_get_name: - * @object: GstObject to get the name of + * @object: a #GstObject to get the name of * - * Get the name of the object. This function returns a copy - * of the name, you should call g_free() on it after usage. + * Returns a copy of the name of the object. + * Caller should g_free() the return value after usage. + * For a nameless object, this returns NULL, which you can safely g_free() + * as well. * - * Returns: name of the object. g_free() after usage. + * Returns: the name of the object. g_free() after usage. * * MT safe. */ diff --git a/gst/gsttypes.h b/gst/gsttypes.h index 8182ff8aa8..335f7024c6 100644 --- a/gst/gsttypes.h +++ b/gst/gsttypes.h @@ -22,9 +22,7 @@ #include -G_BEGIN_DECLS - -typedef struct _GstObject GstObject; +G_BEGIN_DECLS typedef struct _GstObject GstObject; typedef struct _GstObjectClass GstObjectClass; typedef struct _GstPad GstPad; typedef struct _GstPadClass GstPadClass; @@ -36,36 +34,42 @@ typedef struct _GstBin GstBin; typedef struct _GstBinClass GstBinClass; typedef struct _GstPipeline GstPipeline; typedef struct _GstPipelineClass GstPipelineClass; +typedef struct _GstBus GstBus; +typedef struct _GstBusClass GstBusClass; typedef struct _GstScheduler GstScheduler; typedef struct _GstSchedulerClass GstSchedulerClass; typedef struct _GstEvent GstEvent; typedef struct _GstMessage GstMessage; -typedef enum { - GST_STATE_VOID_PENDING = 0, - GST_STATE_NULL = (1 << 0), - GST_STATE_READY = (1 << 1), - GST_STATE_PAUSED = (1 << 2), - GST_STATE_PLAYING = (1 << 3) +typedef enum +{ + GST_STATE_VOID_PENDING = 0, + GST_STATE_NULL = (1 << 0), + GST_STATE_READY = (1 << 1), + GST_STATE_PAUSED = (1 << 2), + GST_STATE_PLAYING = (1 << 3) } GstElementState; -typedef enum { - GST_STATE_FAILURE = 0, - GST_STATE_SUCCESS = 1, - GST_STATE_ASYNC = 2 +typedef enum +{ + GST_STATE_FAILURE = 0, + GST_STATE_SUCCESS = 1, + GST_STATE_ASYNC = 2 } GstElementStateReturn; -typedef enum { +typedef enum +{ GST_RESULT_OK, GST_RESULT_NOK, GST_RESULT_NOT_IMPL } GstResult; -typedef enum { - GST_RANK_NONE = 0, - GST_RANK_MARGINAL = 64, - GST_RANK_SECONDARY = 128, - GST_RANK_PRIMARY = 256 +typedef enum +{ + GST_RANK_NONE = 0, + GST_RANK_MARGINAL = 64, + GST_RANK_SECONDARY = 128, + GST_RANK_PRIMARY = 256 } GstRank; #define GST_PADDING 4 @@ -73,5 +77,4 @@ typedef enum { G_END_DECLS - #endif /* __GST_TYPES_H__ */ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am new file mode 100644 index 0000000000..54493ef8e6 --- /dev/null +++ b/tests/check/Makefile.am @@ -0,0 +1,4 @@ +TESTS = gst / gstobject check_PROGRAMS = $ (TESTS) + + AM_CFLAGS = $ (GST_OBJ_CFLAGS) $ (CHECK_CFLAGS) + LDADD = $ (GST_OBJ_LIBS) $ (CHECK_LIBS) diff --git a/tests/check/gst/.gitignore b/tests/check/gst/.gitignore new file mode 100644 index 0000000000..151b49f251 --- /dev/null +++ b/tests/check/gst/.gitignore @@ -0,0 +1 @@ +gstobject diff --git a/tests/check/gst/gstobject.c b/tests/check/gst/gstobject.c new file mode 100644 index 0000000000..6a9eb985ea --- /dev/null +++ b/tests/check/gst/gstobject.c @@ -0,0 +1,162 @@ +/* GStreamer + * + * unit test for GstObject + * + * Copyright (C) <2004> Thomas Vander Stichele + * + * 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. + */ + +#include +#include +#include + +#include + +#include + +/* + Create a fake subclass + */ +typedef struct _GstFakeObjectClass GstFakeObjectClass; +typedef struct _GstFakeObject GstFakeObject; + +struct _GstFakeObject +{ + GstObject object; +}; + +struct _GstFakeObjectClass +{ + GstObjectClass parent_class; +}; + +GType _gst_fake_object_type = 0; + +//static GstObjectClass *parent_class = NULL; +//static guint gst_fake_object_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_fake_object_get_type (void) +{ + if (!_gst_fake_object_type) { + static const GTypeInfo fake_object_info = { + sizeof (GstFakeObjectClass), + NULL, //gst_fake_object_base_class_init, + NULL, //gst_fake_object_base_class_finalize, + NULL, //(GClassInitFunc) gst_fake_object_class_init, + NULL, + NULL, + sizeof (GstFakeObject), + 0, + NULL, //(GInstanceInitFunc) gst_fake_object_init, + NULL + }; + + _gst_fake_object_type = g_type_register_static (GST_TYPE_OBJECT, + "GstFakeObject", &fake_object_info, 0); + } + return _gst_fake_object_type; +} + +/* g_object_new on abstract GstObject should fail */ +START_TEST (test_fail_abstract_new) +{ + GstObject *object; + + object = g_object_new (gst_object_get_type (), NULL); + /* this should assert and segfault, but we add fallbacks anyway */ + fail_unless (object == NULL, "Created an instance of abstract GstObject"); +} + +END_TEST +/* g_object_new on GstFakeObject should succeed */ +START_TEST (test_fake_object_new) +{ + GstObject *object; + + object = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object == NULL, "Failed to create instance of GstFakeObject"); + fail_unless (GST_IS_OBJECT (object), + "GstFakeObject instance is not a GstObject"); +} + +END_TEST +/* GstFakeObject name tests */ +START_TEST (test_fake_object_name) +{ + GstObject *object; + gchar *name; + gchar *name2; + + object = g_object_new (gst_fake_object_get_type (), NULL); + + name = gst_object_get_name (object); + fail_if (name != NULL, "Newly created object has a name"); + + /* give a random name by setting with NULL; + * GstFakeObject class -> fakeobject%d */ + gst_object_set_name (object, NULL); + name = gst_object_get_name (object); + fail_if (name == NULL, "Random name was not assigned"); + fail_if (strncmp (name, "fakeobject", 10) != 0, + "Random name %s does not start with Gst", name); + g_free (name); + + gst_object_set_name (object, "fake"); + name = gst_object_get_name (object); + fail_if (name == NULL, "Failed to get name of GstFakeObject"); + fail_if (strcmp (name, "fake") != 0, "Name of GstFakeObject is not 'fake'"); + + /* change the gotten name to see that it's a copy and not the original */ + name[0] = 'm'; + name2 = gst_object_get_name (object); + fail_if (strcmp (name2, "fake") != 0, + "Copy of object name affected actual object name"); + g_free (name); + g_free (name2); +} + +END_TEST Suite * +gst_object_suite (void) +{ + Suite *s = suite_create ("GstObject"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test_raise_signal (tc_chain, test_fail_abstract_new, SIGSEGV); + tcase_add_test (tc_chain, test_fake_object_new); + tcase_add_test (tc_chain, test_fake_object_name); + //tcase_add_checked_fixture (tc_chain, setup, teardown); + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = gst_object_suite (); + SRunner *sr = srunner_create (s); + + gst_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +} diff --git a/tools/gst-launch.c b/tools/gst-launch.c index 9c3aad87f1..c72280484e 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -337,7 +337,8 @@ message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) break; case GST_MESSAGE_ERROR: gst_object_default_error (GST_MESSAGE_SRC (message), - GST_MESSAGE_ERROR_ERROR (message), GST_MESSAGE_ERROR_DEBUG (message)); + GST_MESSAGE_ERROR_GERROR (message), + GST_MESSAGE_ERROR_DEBUG (message)); caught_error = TRUE; gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); if (g_main_loop_is_running (loop))