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>
* 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));
}
/* 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"));
}

View file

@ -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__ */

View file

@ -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);

View file

@ -7,63 +7,66 @@
#include <gst/gst.h>
#include <locale.h>
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);