tools/gst-launch.c: Update to use the new message-parsing API.

Original commit message from CVS:
2005-03-03  Andy Wingo  <wingo@pobox.com>

* 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.
This commit is contained in:
Andy Wingo 2005-03-03 15:37:39 +00:00
parent 70d2a801d9
commit 9a14160bee
5 changed files with 236 additions and 151 deletions

View file

@ -1,3 +1,20 @@
2005-03-03 Andy Wingo <wingo@pobox.com>
* 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 <wingo@pobox.com> 2005-03-01 Andy Wingo <wingo@pobox.com>
* tests/complexity.c: Adjust to lack of gst_bin_iterate, boolean * tests/complexity.c: Adjust to lack of gst_bin_iterate, boolean

View file

@ -73,16 +73,8 @@ _gst_message_copy (GstMessage * message)
gst_object_ref (GST_MESSAGE_SRC (copy)); gst_object_ref (GST_MESSAGE_SRC (copy));
} }
/* FIXME copy/ref additional fields */ if (copy->structure)
switch (GST_MESSAGE_TYPE (message)) { copy->structure = gst_structure_copy (copy->structure);
case GST_MESSAGE_TAG:
copy->message_data.structure.structure =
gst_tag_list_copy ((GstTagList *) message->message_data.structure.
structure);
break;
default:
break;
}
return copy; return copy;
} }
@ -95,34 +87,16 @@ _gst_message_free (GstMessage * message)
if (GST_MESSAGE_SRC (message)) { if (GST_MESSAGE_SRC (message)) {
gst_object_unref (GST_MESSAGE_SRC (message)); gst_object_unref (GST_MESSAGE_SRC (message));
} }
if (message->lock) { if (message->lock) {
GST_MESSAGE_LOCK (message); GST_MESSAGE_LOCK (message);
GST_MESSAGE_SIGNAL (message); GST_MESSAGE_SIGNAL (message);
GST_MESSAGE_UNLOCK (message); GST_MESSAGE_UNLOCK (message);
} }
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR: if (message->structure)
case GST_MESSAGE_WARNING: gst_structure_free (message->structure);
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;
}
_GST_DATA_DISPOSE (GST_DATA (message)); _GST_DATA_DISPOSE (GST_DATA (message));
#ifndef GST_DISABLE_TRACE #ifndef GST_DISABLE_TRACE
gst_alloc_trace_free (_message_trace, message); gst_alloc_trace_free (_message_trace, message);
@ -196,8 +170,12 @@ gst_message_new_eos (GstObject * src)
/** /**
* gst_message_new_error: * 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. * Returns: The new error message.
* *
@ -207,18 +185,24 @@ GstMessage *
gst_message_new_error (GstObject * src, GError * error, gchar * debug) gst_message_new_error (GstObject * src, GError * error, gchar * debug)
{ {
GstMessage *message; GstMessage *message;
GstStructure *s;
message = gst_message_new (GST_MESSAGE_ERROR, src); message = gst_message_new (GST_MESSAGE_ERROR, src);
GST_MESSAGE_ERROR_GERROR (message) = error; s = gst_structure_new ("GstMessageError", "gerror", G_TYPE_POINTER, error,
GST_MESSAGE_ERROR_DEBUG (message) = debug; "debug", G_TYPE_STRING, debug, NULL);
message->structure = s;
return message; return message;
} }
/** /**
* gst_message_new_warning: * 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. * Returns: The new warning message.
* *
@ -228,18 +212,22 @@ GstMessage *
gst_message_new_warning (GstObject * src, GError * error, gchar * debug) gst_message_new_warning (GstObject * src, GError * error, gchar * debug)
{ {
GstMessage *message; GstMessage *message;
GstStructure *s;
message = gst_message_new (GST_MESSAGE_WARNING, src); message = gst_message_new (GST_MESSAGE_WARNING, src);
GST_MESSAGE_WARNING_GERROR (message) = error; s = gst_structure_new ("GstMessageWarning", "gerror", G_TYPE_POINTER, error,
GST_MESSAGE_WARNING_DEBUG (message) = debug; "debug", G_TYPE_STRING, debug, NULL);
message->structure = s;
return message; return message;
} }
/** /**
* gst_message_new_tag: * 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. * Returns: The new tag message.
* *
@ -251,13 +239,16 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list)
GstMessage *message; GstMessage *message;
message = gst_message_new (GST_MESSAGE_TAG, src); message = gst_message_new (GST_MESSAGE_TAG, src);
GST_MESSAGE_TAG_LIST (message) = tag_list; message->structure = tag_list;
return message; return message;
} }
/** /**
* gst_message_new_state_change: * 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. * Create a state change message.
* *
@ -270,10 +261,12 @@ gst_message_new_state_changed (GstObject * src, GstElementState old,
GstElementState new) GstElementState new)
{ {
GstMessage *message; GstMessage *message;
GstStructure *s;
message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src); message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src);
message->message_data.state_changed.old = old; s = gst_structure_new ("GstMessageError", "old-state", G_TYPE_INT, old,
message->message_data.state_changed.new = new; "new-state", G_TYPE_INT, new, NULL);
message->structure = s;
return message; return message;
} }
@ -296,7 +289,114 @@ gst_message_new_application (GstStructure * structure)
GstMessage *message; GstMessage *message;
message = gst_message_new (GST_MESSAGE_APPLICATION, NULL); message = gst_message_new (GST_MESSAGE_APPLICATION, NULL);
message->message_data.structure.structure = structure; message->structure = structure;
return message; 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"));
}

View file

@ -89,19 +89,6 @@ typedef enum
#define GST_MESSAGE_TIMESTAMP(message) (GST_MESSAGE(message)->timestamp) #define GST_MESSAGE_TIMESTAMP(message) (GST_MESSAGE(message)->timestamp)
#define GST_MESSAGE_SRC(message) (GST_MESSAGE(message)->src) #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 struct _GstMessage
{ {
GstData data; GstData data;
@ -115,28 +102,8 @@ struct _GstMessage
guint64 timestamp; guint64 timestamp;
GstObject *src; GstObject *src;
union GstStructure *structure;
{
struct
{
GError *gerror;
gchar *debug;
} error;
struct
{
GstStructure *structure;
} structure;
struct
{
GstTagList *list;
} tag;
struct
{
GstElementState old;
GstElementState new;
} state_changed;
} message_data;
/*< private > */ /*< private > */
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
@ -161,5 +128,14 @@ GstMessage * gst_message_new_state_changed (GstObject * src, GstElementState ol
GstElementState new); GstElementState new);
GstMessage * gst_message_new_application (GstStructure *structure); 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 G_END_DECLS
#endif /* __GST_MESSAGE_H__ */ #endif /* __GST_MESSAGE_H__ */

View file

@ -339,7 +339,6 @@ event_loop (GstElement * pipeline, gboolean blocking)
GstBus *bus; GstBus *bus;
GstMessageType revent; GstMessageType revent;
GstMessage *message = NULL; GstMessage *message = NULL;
GstElementState old, new;
bus = gst_element_get_bus (GST_ELEMENT (pipeline)); bus = gst_element_get_bus (GST_ELEMENT (pipeline));
@ -361,21 +360,32 @@ event_loop (GstElement * pipeline, gboolean blocking)
return FALSE; return FALSE;
case GST_MESSAGE_TAG: case GST_MESSAGE_TAG:
if (tags) { if (tags) {
GstTagList *tags;
gst_message_parse_tag (message, &tags);
g_print (_("FOUND TAG : found by element \"%s\".\n"), g_print (_("FOUND TAG : found by element \"%s\".\n"),
GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
gst_tag_list_foreach (GST_MESSAGE_TAG_LIST (message), print_tag, gst_tag_list_foreach (tags, print_tag, NULL);
NULL); gst_tag_list_free (tags);
} }
gst_message_unref (message); gst_message_unref (message);
break; break;
case GST_MESSAGE_ERROR: case GST_MESSAGE_WARNING:
gst_object_default_error (GST_MESSAGE_SRC (message), case GST_MESSAGE_ERROR:{
GST_MESSAGE_ERROR_GERROR (message), GError *gerror;
GST_MESSAGE_ERROR_DEBUG (message)); gchar *debug;
gst_message_parse_error (message, &gerror, &debug);
gst_message_unref (message); gst_message_unref (message);
gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
g_error_free (gerror);
g_free (debug);
return TRUE; 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); gst_message_unref (message);
if (!(old == GST_STATE_PLAYING && new == GST_STATE_PAUSED)) if (!(old == GST_STATE_PLAYING && new == GST_STATE_PAUSED))
break; break;
@ -384,6 +394,7 @@ event_loop (GstElement * pipeline, gboolean blocking)
GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
/* cut out of the event loop if check_intr set us to PAUSED */ /* cut out of the event loop if check_intr set us to PAUSED */
return FALSE; return FALSE;
}
default: default:
/* just be quiet by default */ /* just be quiet by default */
gst_message_unref (message); gst_message_unref (message);

View file

@ -7,63 +7,66 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <locale.h> #include <locale.h>
static GMainLoop *loop; /* blocking */
static gboolean static gboolean
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) event_loop (GstElement * pipeline)
{ {
switch (GST_MESSAGE_TYPE (message)) { GstBus *bus;
case GST_MESSAGE_EOS: GstMessageType revent;
if (g_main_loop_is_running (loop)) GstMessage *message = NULL;
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);
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; return TRUE;
} }
int int
main (int argc, char *argv[]) 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; GstElement *pipeline = NULL;
gchar **argvn;
GError *error = NULL; GError *error = NULL;
GstElement *md5sink; GstElement *md5sink;
gchar **argvn;
gchar *md5string = g_malloc0 (33); gchar *md5string = g_malloc0 (33);
free (malloc (8)); /* -lefence */ free (malloc (8)); /* -lefence */
setlocale (LC_ALL, ""); 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); argvn = g_new0 (char *, argc);
memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
pipeline = (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
/* 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);
if (!pipeline) { if (!pipeline) {
if (error) { if (error) {
g_warning ("pipeline could not be constructed: %s\n", error->message); 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"); md5sink = gst_bin_get_by_name (GST_BIN (pipeline), "md5sink0");
if (md5sink == NULL) { if (md5sink == NULL) {
g_print ("adding an md5sink element to the pipeline\n"); g_print ("ERROR: pipeline has no element named md5sink0.\n");
/* make a null-terminated version of argv with ! md5sink appended g_print ("Did you forget to put an md5sink in the pipeline?\n");
* ! is stored in argvn[argc - 1], md5sink in argvn[argc], return 1;
* 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);
} }
if (!pipeline) { if (!pipeline) {
@ -97,26 +92,12 @@ main (int argc, char *argv[])
return 1; 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) { if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
g_warning ("pipeline doesn't want to play\n"); 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); gst_element_set_state (pipeline, GST_STATE_NULL);