diff --git a/ChangeLog b/ChangeLog index f695c09783..47657e2dfb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2005-03-03 Andy Wingo + + * tools/gst-launch.c: Update to use the new message-parsing API. + + * tools/gst-md5sum.c: Update to new spiffy poll API. Not that + md5sum is ported though! + + * gst/gstmessage.c: + * gst/gstmessage.h (struct _GstMessage): Changed so the message + data is just a GstStructure, not a union. + (gst_message_get_structure): New function, gets the structure + backing the message. Owned by the message. + (gst_message_parse_tag, gst_message_parse_state_changed) + (gst_message_parse_error, gst_message_parse_warning): New + functions, parse the message into their components. Return values + are copies, and so must be freed by the caller. + 2005-03-01 Andy Wingo * tests/complexity.c: Adjust to lack of gst_bin_iterate, boolean diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 3ea12da315..f51aa2d1f0 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -73,16 +73,8 @@ _gst_message_copy (GstMessage * message) gst_object_ref (GST_MESSAGE_SRC (copy)); } - /* FIXME copy/ref additional fields */ - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_TAG: - copy->message_data.structure.structure = - gst_tag_list_copy ((GstTagList *) message->message_data.structure. - structure); - break; - default: - break; - } + if (copy->structure) + copy->structure = gst_structure_copy (copy->structure); return copy; } @@ -95,34 +87,16 @@ _gst_message_free (GstMessage * message) if (GST_MESSAGE_SRC (message)) { gst_object_unref (GST_MESSAGE_SRC (message)); } + if (message->lock) { GST_MESSAGE_LOCK (message); GST_MESSAGE_SIGNAL (message); GST_MESSAGE_UNLOCK (message); } - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR: - case GST_MESSAGE_WARNING: - g_error_free (GST_MESSAGE_ERROR_GERROR (message)); - g_free (GST_MESSAGE_ERROR_DEBUG (message)); - break; - case GST_MESSAGE_TAG: - if (GST_IS_TAG_LIST (message->message_data.tag.list)) { - gst_tag_list_free (message->message_data.tag.list); - } else { - g_warning ("tag message %p didn't contain a valid tag list!", message); - GST_ERROR ("tag message %p didn't contain a valid tag list!", message); - } - break; - case GST_MESSAGE_APPLICATION: - if (message->message_data.structure.structure) { - gst_structure_free (message->message_data.structure.structure); - message->message_data.structure.structure = NULL; - } - break; - default: - break; - } + + if (message->structure) + gst_structure_free (message->structure); + _GST_DATA_DISPOSE (GST_DATA (message)); #ifndef GST_DISABLE_TRACE gst_alloc_trace_free (_message_trace, message); @@ -196,8 +170,12 @@ gst_message_new_eos (GstObject * src) /** * gst_message_new_error: + * @src: The object originating the message. + * @error: The GError for this message. + * @debug: A debugging string for something or other. * - * Create a new error message. + * Create a new error message. The message will take ownership of @error and + * @debug. * * Returns: The new error message. * @@ -207,18 +185,24 @@ GstMessage * gst_message_new_error (GstObject * src, GError * error, gchar * debug) { GstMessage *message; + GstStructure *s; message = gst_message_new (GST_MESSAGE_ERROR, src); - GST_MESSAGE_ERROR_GERROR (message) = error; - GST_MESSAGE_ERROR_DEBUG (message) = debug; + s = gst_structure_new ("GstMessageError", "gerror", G_TYPE_POINTER, error, + "debug", G_TYPE_STRING, debug, NULL); + message->structure = s; return message; } /** * gst_message_new_warning: + * @src: The object originating the message. + * @error: The GError for this message. + * @debug: A debugging string for something or other. * - * Create a new warning message. + * Create a new warning message. The message will take ownership of @error and + * @debug. * * Returns: The new warning message. * @@ -228,18 +212,22 @@ GstMessage * gst_message_new_warning (GstObject * src, GError * error, gchar * debug) { GstMessage *message; + GstStructure *s; message = gst_message_new (GST_MESSAGE_WARNING, src); - GST_MESSAGE_WARNING_GERROR (message) = error; - GST_MESSAGE_WARNING_DEBUG (message) = debug; + s = gst_structure_new ("GstMessageWarning", "gerror", G_TYPE_POINTER, error, + "debug", G_TYPE_STRING, debug, NULL); + message->structure = s; return message; } /** * gst_message_new_tag: + * @src: The object originating the message. + * @tag_list: The tag list for the message. * - * Create a new tag message. + * Create a new tag message. The message will take ownership of the tag list. * * Returns: The new tag message. * @@ -251,13 +239,16 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list) GstMessage *message; message = gst_message_new (GST_MESSAGE_TAG, src); - GST_MESSAGE_TAG_LIST (message) = tag_list; + message->structure = tag_list; return message; } /** * gst_message_new_state_change: + * @src: The object originating the message. + * @old: The previous state. + * @new: The new (current) state. * * Create a state change message. * @@ -270,10 +261,12 @@ gst_message_new_state_changed (GstObject * src, GstElementState old, GstElementState new) { GstMessage *message; + GstStructure *s; message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src); - message->message_data.state_changed.old = old; - message->message_data.state_changed.new = new; + s = gst_structure_new ("GstMessageError", "old-state", G_TYPE_INT, old, + "new-state", G_TYPE_INT, new, NULL); + message->structure = s; return message; } @@ -296,7 +289,114 @@ gst_message_new_application (GstStructure * structure) GstMessage *message; message = gst_message_new (GST_MESSAGE_APPLICATION, NULL); - message->message_data.structure.structure = structure; + message->structure = structure; return message; } + +/** + * gst_message_get_structure: + * @message: The #GstMessage. + * + * Access the structure of the message. + * + * Returns: The structure of the message, owned by the message. + * + * MT safe. + */ +const GstStructure * +gst_message_get_structure (GstMessage * message) +{ + g_return_val_if_fail (GST_IS_MESSAGE (message), NULL); + return message->structure; +} + +/** + * gst_message_parse_tag: + * @message: A valid #GstMessage of type GST_MESSAGE_TAG. + * + * Extracts the tag list from the GstMessage. The tag list returned in the + * output argument is a copy; the caller must free it when done. + * + * MT safe. + */ +void +gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG); + + *tag_list = (GstTagList *) gst_structure_copy (message->structure); +} + +/** + * gst_message_parse_tag: + * @message: A valid #GstMessage of type GST_MESSAGE_STATE_CHANGED. + * + * Extracts the old and new states from the GstMessage. + * + * MT safe. + */ +void +gst_message_parse_state_changed (GstMessage * message, GstElementState * old, + GstElementState * new) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED); + + if (!gst_structure_get_int (message->structure, "old-state", (gint *) old)) + g_assert_not_reached (); + if (!gst_structure_get_int (message->structure, "new-state", (gint *) new)) + g_assert_not_reached (); +} + +/** + * gst_message_parse_error: + * @message: A valid #GstMessage of type GST_MESSAGE_ERROR. + * + * Extracts the GError and debug strung from the GstMessage. The values returned + * in the output arguments are copies; the caller must free them when done. + * + * MT safe. + */ +void +gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug) +{ + const GValue *error_gvalue; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR); + + error_gvalue = gst_structure_get_value (message->structure, "gerror"); + g_return_if_fail (error_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_POINTER); + + *gerror = g_error_copy (g_value_get_pointer (error_gvalue)); + *debug = g_strdup (gst_structure_get_string (message->structure, "debug")); +} + +/** + * gst_message_parse_warning: + * @message: A valid #GstMessage of type GST_MESSAGE_WARNING. + * + * Extracts the GError and debug strung from the GstMessage. The values returned + * in the output arguments are copies; the caller must free them when done. + * + * MT safe. + */ +void +gst_message_parse_warning (GstMessage * message, GError ** gerror, + gchar ** debug) +{ + const GValue *error_gvalue; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING); + + error_gvalue = gst_structure_get_value (message->structure, "gerror"); + g_return_if_fail (error_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_POINTER); + + *gerror = g_error_copy (g_value_get_pointer (error_gvalue)); + *debug = g_strdup (gst_structure_get_string (message->structure, "debug")); +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h index b1c4a299b1..1dc9a882bb 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -89,19 +89,6 @@ typedef enum #define GST_MESSAGE_TIMESTAMP(message) (GST_MESSAGE(message)->timestamp) #define GST_MESSAGE_SRC(message) (GST_MESSAGE(message)->src) -#define GST_MESSAGE_TAG_LIST(message) (GST_MESSAGE(message)->message_data.tag.list) - -/* this is terribly nasty cause I'm going to make these all functions soon */ -#define GST_MESSAGE_PARSE_STATE_CHANGED(message, pold, pnew) G_STMT_START{ \ - *pold = GST_MESSAGE(message)->message_data.state_changed.old; \ - *pnew = GST_MESSAGE(message)->message_data.state_changed.new; \ -}G_STMT_END - -#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 { GstData data; @@ -115,28 +102,8 @@ struct _GstMessage guint64 timestamp; GstObject *src; - union - { - struct - { - GError *gerror; - gchar *debug; - } error; - struct - { - GstStructure *structure; - } structure; - struct - { - GstTagList *list; - } tag; - struct - { - GstElementState old; - GstElementState new; - } state_changed; - } message_data; - + GstStructure *structure; + /*< private > */ gpointer _gst_reserved[GST_PADDING]; }; @@ -161,5 +128,14 @@ GstMessage * gst_message_new_state_changed (GstObject * src, GstElementState ol GstElementState new); GstMessage * gst_message_new_application (GstStructure *structure); +const GstStructure * gst_message_get_structure (GstMessage *message); + +void gst_message_parse_tag (GstMessage *message, GstTagList **tag_list); +void gst_message_parse_state_changed (GstMessage *message, GstElementState *old, + GstElementState *new); +void gst_message_parse_error (GstMessage *message, GError **gerror, gchar **debug); +void gst_message_parse_warning (GstMessage *message, GError **gerror, gchar **debug); + + G_END_DECLS #endif /* __GST_MESSAGE_H__ */ diff --git a/tools/gst-launch.c b/tools/gst-launch.c index 1dda0b563d..cc865bc8cd 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -339,7 +339,6 @@ event_loop (GstElement * pipeline, gboolean blocking) GstBus *bus; GstMessageType revent; GstMessage *message = NULL; - GstElementState old, new; bus = gst_element_get_bus (GST_ELEMENT (pipeline)); @@ -361,21 +360,32 @@ event_loop (GstElement * pipeline, gboolean blocking) return FALSE; case GST_MESSAGE_TAG: if (tags) { + GstTagList *tags; + + gst_message_parse_tag (message, &tags); g_print (_("FOUND TAG : found by element \"%s\".\n"), GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); - gst_tag_list_foreach (GST_MESSAGE_TAG_LIST (message), print_tag, - NULL); + gst_tag_list_foreach (tags, print_tag, NULL); + gst_tag_list_free (tags); } gst_message_unref (message); break; - case GST_MESSAGE_ERROR: - gst_object_default_error (GST_MESSAGE_SRC (message), - GST_MESSAGE_ERROR_GERROR (message), - GST_MESSAGE_ERROR_DEBUG (message)); + case GST_MESSAGE_WARNING: + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); gst_message_unref (message); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); return TRUE; - case GST_MESSAGE_STATE_CHANGED: - GST_MESSAGE_PARSE_STATE_CHANGED (message, &old, &new); + } + case GST_MESSAGE_STATE_CHANGED:{ + GstElementState old, new; + + gst_message_parse_state_changed (message, &old, &new); gst_message_unref (message); if (!(old == GST_STATE_PLAYING && new == GST_STATE_PAUSED)) break; @@ -384,6 +394,7 @@ event_loop (GstElement * pipeline, gboolean blocking) GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); /* cut out of the event loop if check_intr set us to PAUSED */ return FALSE; + } default: /* just be quiet by default */ gst_message_unref (message); diff --git a/tools/gst-md5sum.c b/tools/gst-md5sum.c index cabf2c4e1b..33f7d8eb6f 100644 --- a/tools/gst-md5sum.c +++ b/tools/gst-md5sum.c @@ -7,63 +7,66 @@ #include #include -static GMainLoop *loop; - +/* blocking */ static gboolean -message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +event_loop (GstElement * pipeline) { - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_EOS: - if (g_main_loop_is_running (loop)) - g_main_loop_quit (loop); - break; - case GST_MESSAGE_ERROR: - gst_object_default_error (GST_MESSAGE_SRC (message), - GST_MESSAGE_ERROR_GERROR (message), - GST_MESSAGE_ERROR_DEBUG (message)); - if (g_main_loop_is_running (loop)) - g_main_loop_quit (loop); - break; - default: - break; - } - gst_message_unref (message); + GstBus *bus; + GstMessageType revent; + GstMessage *message = NULL; + bus = gst_element_get_bus (GST_ELEMENT (pipeline)); + + while (TRUE) { + revent = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); + + message = gst_bus_pop (bus); + g_return_val_if_fail (message != NULL, TRUE); + + switch (revent) { + case GST_MESSAGE_EOS: + gst_message_unref (message); + return FALSE; + case GST_MESSAGE_WARNING: + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_message_unref (message); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + return TRUE; + } + default: + gst_message_unref (message); + break; + } + } + + g_assert_not_reached (); return TRUE; } - int main (int argc, char *argv[]) { - /* options */ - gboolean verbose = FALSE; - gchar *exclude_args = NULL; - struct poptOption options[] = { - {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0, - "do not output status information", NULL}, - POPT_TABLEEND - }; - GstElement *pipeline = NULL; - gchar **argvn; GError *error = NULL; GstElement *md5sink; + gchar **argvn; gchar *md5string = g_malloc0 (33); free (malloc (8)); /* -lefence */ setlocale (LC_ALL, ""); - gst_init_with_popt_table (&argc, &argv, options); + gst_init (&argc, &argv); - /* make a parseable argvn array */ argvn = g_new0 (char *, argc); memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); - - /* Check if we have an element already that is called md5sink0 - in the pipeline; if not, add one */ - //pipeline = (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error); + pipeline = (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error); if (!pipeline) { if (error) { g_warning ("pipeline could not be constructed: %s\n", error->message); @@ -75,17 +78,9 @@ main (int argc, char *argv[]) md5sink = gst_bin_get_by_name (GST_BIN (pipeline), "md5sink0"); if (md5sink == NULL) { - g_print ("adding an md5sink element to the pipeline\n"); - /* make a null-terminated version of argv with ! md5sink appended - * ! is stored in argvn[argc - 1], md5sink in argvn[argc], - * NULL pointer in argvn[argc + 1] */ - g_free (argvn); - argvn = g_new0 (char *, argc + 2); - memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); - argvn[argc - 1] = g_strdup_printf ("!"); - argvn[argc] = g_strdup_printf ("md5sink"); - pipeline = - (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error); + g_print ("ERROR: pipeline has no element named md5sink0.\n"); + g_print ("Did you forget to put an md5sink in the pipeline?\n"); + return 1; } if (!pipeline) { @@ -97,26 +92,12 @@ main (int argc, char *argv[]) return 1; } - if (verbose) { - gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0) - : NULL; - - g_signal_connect (pipeline, "deep_notify", - G_CALLBACK (gst_object_default_deep_notify), exclude_list); - } - //g_signal_connect (pipeline, "error", - // G_CALLBACK (gst_object_default_error), NULL); - - loop = g_main_loop_new (NULL, FALSE); - gst_bus_add_watch (gst_element_get_bus (GST_ELEMENT (pipeline)), - (GstBusHandler) message_received, pipeline); - if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) { g_warning ("pipeline doesn't want to play\n"); - return 0; + return 1; } - g_main_loop_run (loop); + event_loop (pipeline); gst_element_set_state (pipeline, GST_STATE_NULL);