gst/gstmessage.h (GstMessageType): Turned into flags. Added

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

* gst/gstmessage.h (GstMessageType): Turned into flags. Added
GST_MESSAGE_ANY as an OR of all flags.
(GST_MESSAGE_PARSE_STATE_CHANGED): New terrible macro. Will be
made into a function soon.
(GstMessage): Add a state_changed structure to the union. The
union will die soon in favor of a single GstStructure tho.
(gst_message_new_state_changed): New API.

* gst/gstmessage.c (gst_message_new_state_changed): New API.

* tools/gst-launch.c (check_intr): Set the state of the pipeline
to PAUSED here; the poll will catch the state change.
(event_loop): New function, polls the pipeline bus for events. Can
block until eos/error/state change, or just handle the pending
events.
(main): Changed to use event_loop instead of running a main loop.

* gst/gstbus.h (gst_bus_poll): Added.
(gst_bus_peek): Return non-const; the message is refcounted
anyway.

* gst/gstbus.c (gst_bus_init): Replace the GAsyncQueue with a
GQueue+mutex to allow for _peek. (The wake-up functionality
provided by GAsyncQueue is already done by our socketpair.) All
queue users changed to lock, operate, and unlock.
(gst_bus_post): Check the retval of write(2) and handle errno.
(gst_bus_peek): Implemented.
(gst_bus_pop, gst_bus_peek, bus_callback): Because the socketpair
is used to wake up the GSource, read off the character in the
GSource handler and not in pop/peek. This is because a peek will
require a pop in the future, and you can't read off the char
twice. Deal with errno in the read.
(bus_callback): Interpret the handler return value as whether or
not to pop the message from the bus.
(poll_handler, poll_timeout, gst_bus_poll): New API. gst_bus_poll
is meant to replace the while(gst_bin_iterate()) idiom.
This commit is contained in:
Andy Wingo 2005-02-21 11:54:55 +00:00
parent 69e9ca3e5f
commit 1a5201826c
7 changed files with 360 additions and 101 deletions

View file

@ -1,3 +1,42 @@
2005-02-21 Andy Wingo <wingo@pobox.com>
* gst/gstmessage.h (GstMessageType): Turned into flags. Added
GST_MESSAGE_ANY as an OR of all flags.
(GST_MESSAGE_PARSE_STATE_CHANGED): New terrible macro. Will be
made into a function soon.
(GstMessage): Add a state_changed structure to the union. The
union will die soon in favor of a single GstStructure tho.
(gst_message_new_state_changed): New API.
* gst/gstmessage.c (gst_message_new_state_changed): New API.
* tools/gst-launch.c (check_intr): Set the state of the pipeline
to PAUSED here; the poll will catch the state change.
(event_loop): New function, polls the pipeline bus for events. Can
block until eos/error/state change, or just handle the pending
events.
(main): Changed to use event_loop instead of running a main loop.
* gst/gstbus.h (gst_bus_poll): Added.
(gst_bus_peek): Return non-const; the message is refcounted
anyway.
* gst/gstbus.c (gst_bus_init): Replace the GAsyncQueue with a
GQueue+mutex to allow for _peek. (The wake-up functionality
provided by GAsyncQueue is already done by our socketpair.) All
queue users changed to lock, operate, and unlock.
(gst_bus_post): Check the retval of write(2) and handle errno.
(gst_bus_peek): Implemented.
(gst_bus_pop, gst_bus_peek, bus_callback): Because the socketpair
is used to wake up the GSource, read off the character in the
GSource handler and not in pop/peek. This is because a peek will
require a pop in the future, and you can't read off the char
twice. Deal with errno in the read.
(bus_callback): Interpret the handler return value as whether or
not to pop the message from the bus.
(poll_handler, poll_timeout, gst_bus_poll): New API. gst_bus_poll
is meant to replace the while(gst_bin_iterate()) idiom.
2005-02-18 Andy Wingo <wingo@pobox.com>
* gst/elements/gstfakesrc.c (gst_fakesrc_class_init): Add HAS_LOOP

View file

@ -20,6 +20,7 @@
*/
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -93,7 +94,8 @@ gst_bus_class_init (GstBusClass * klass)
static void
gst_bus_init (GstBus * bus)
{
bus->queue = g_async_queue_new ();
bus->queue = g_queue_new ();
bus->queue_lock = g_mutex_new ();
if (socketpair (PF_UNIX, SOCK_STREAM, 0, bus->control_socket) < 0)
goto no_socketpair;
@ -126,8 +128,12 @@ gst_bus_dispose (GObject * object)
close (bus->control_socket[1]);
if (bus->queue) {
g_async_queue_unref (bus->queue);
g_mutex_lock (bus->queue_lock);
g_queue_free (bus->queue);
bus->queue = NULL;
g_mutex_unlock (bus->queue_lock);
g_mutex_free (bus->queue_lock);
bus->queue_lock = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
@ -191,6 +197,7 @@ gst_bus_post (GstBus * bus, GstMessage * message)
GstBusSyncReply reply = GST_BUS_PASS;
GstBusSyncHandler handler;
gpointer handler_data;
ssize_t write_ret = -1;
g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
@ -214,9 +221,22 @@ gst_bus_post (GstBus * bus, GstMessage * message)
break;
case GST_BUS_PASS:
/* pass the message to the async queue */
g_async_queue_push (bus->queue, message);
g_mutex_lock (bus->queue_lock);
g_queue_push_tail (bus->queue, message);
g_mutex_unlock (bus->queue_lock);
c = 'p';
write (bus->control_socket[1], &c, 1);
errno = EAGAIN;
while (write_ret == -1) {
switch (errno) {
case EAGAIN:
case EINTR:
break;
default:
perror ("gst_bus_post: could not write to fd");
return FALSE;
}
write_ret = write (bus->control_socket[1], &c, 1);
}
break;
case GST_BUS_ASYNC:
{
@ -234,9 +254,22 @@ gst_bus_post (GstBus * bus, GstMessage * message)
* queue. When the message is handled by the app and destroyed,
* the cond will be signalled and we can continue */
g_mutex_lock (lock);
g_async_queue_push (bus->queue, message);
g_mutex_lock (bus->queue_lock);
g_queue_push_tail (bus->queue, message);
g_mutex_unlock (bus->queue_lock);
c = 'p';
write (bus->control_socket[1], &c, 1);
errno = EAGAIN;
while (write_ret == -1) {
switch (errno) {
case EAGAIN:
case EINTR:
break;
default:
perror ("gst_bus_post: could not write to fd");
return FALSE;
}
write_ret = write (bus->control_socket[1], &c, 1);
}
/* now block till the message is freed */
g_cond_wait (cond, lock);
g_mutex_unlock (lock);
@ -270,7 +303,9 @@ gst_bus_have_pending (GstBus * bus)
g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
length = g_async_queue_length (bus->queue);
g_mutex_lock (bus->queue_lock);
length = g_queue_get_length (bus->queue);
g_mutex_unlock (bus->queue_lock);
return (length > 0);
}
@ -281,8 +316,7 @@ gst_bus_have_pending (GstBus * bus)
*
* Get a message from the bus.
*
* Returns: The #GstMessage that is on the bus or NULL when there are no
* messages available.
* Returns: The #GstMessage that is on the bus, or NULL if the bus is empty.
*
* MT safe.
*/
@ -290,12 +324,37 @@ GstMessage *
gst_bus_pop (GstBus * bus)
{
GstMessage *message;
gchar c;
g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
g_return_val_if_fail (GST_IS_BUS (bus), NULL);
message = g_async_queue_pop (bus->queue);
read (bus->control_socket[0], &c, 1);
g_mutex_lock (bus->queue_lock);
message = g_queue_pop_head (bus->queue);
g_mutex_unlock (bus->queue_lock);
return message;
}
/**
* gst_bus_peek:
* @bus: a #GstBus
*
* Peek the message on the top of the bus' queue. The bus maintains ownership of
* the message, and the message will remain on the bus' message queue.
*
* Returns: The #GstMessage that is on the bus, or NULL if the bus is empty.
*
* MT safe.
*/
GstMessage *
gst_bus_peek (GstBus * bus)
{
GstMessage *message;
g_return_val_if_fail (GST_IS_BUS (bus), NULL);
g_mutex_lock (bus->queue_lock);
message = g_queue_peek_head (bus->queue);
g_mutex_unlock (bus->queue_lock);
return message;
}
@ -357,13 +416,36 @@ static gboolean
bus_callback (GIOChannel * channel, GIOCondition cond, GstBusWatch * watch)
{
GstMessage *message;
gboolean needs_pop = TRUE;
gchar c;
ssize_t read_ret = -1;
g_return_val_if_fail (GST_IS_BUS (watch->bus), FALSE);
message = gst_bus_pop (watch->bus);
/* the char in the fd is essentially just a way to wake us up. read it off so
we're not woken up again. */
errno = EAGAIN;
while (read_ret == -1) {
switch (errno) {
case EAGAIN:
case EINTR:
break;
default:
perror ("gst_bus_pop: could not read from fd");
return TRUE;
}
read_ret = read (watch->bus->control_socket[0], &c, 1);
}
message = gst_bus_peek (watch->bus);
g_return_val_if_fail (message != NULL, TRUE);
if (watch->handler)
watch->handler (watch->bus, message, watch->user_data);
needs_pop = watch->handler (watch->bus, message, watch->user_data);
if (needs_pop)
gst_message_unref (gst_bus_pop (watch->bus));
return TRUE;
}
@ -381,8 +463,12 @@ bus_destroy (GstBusWatch * watch)
/**
* gst_bus_add_watch_full:
* @bus: a #GstBus to create the watch for
* @handler: A function to call when a message is received.
*
* Adds the bus to the mainloop with the given priority.
* Adds the bus to the mainloop with the given priority. If the handler returns
* TRUE, the message will then be popped off the queue. When the handler is
* called, the message belongs to the caller; if you want to keep a copy of it,
* call gst_message_ref before leaving the handler.
*
* Returns: The event source id.
*
@ -435,3 +521,79 @@ gst_bus_add_watch (GstBus * bus, GstBusHandler handler, gpointer user_data)
return gst_bus_add_watch_full (bus, G_PRIORITY_DEFAULT, handler, user_data,
NULL);
}
typedef struct
{
GMainLoop *loop;
guint timeout_id;
GstMessageType events;
GstMessageType revent;
} GstBusPollData;
static gboolean
poll_handler (GstBus * bus, GstMessage * message, GstBusPollData * poll_data)
{
if (GST_MESSAGE_TYPE (message) & poll_data->events) {
poll_data->revent = GST_MESSAGE_TYPE (message);
if (g_main_loop_is_running (poll_data->loop))
g_main_loop_quit (poll_data->loop);
/* keep the message on the queue */
return FALSE;
} else {
/* pop and unref the message */
return TRUE;
}
}
static gboolean
poll_timeout (GstBusPollData * poll_data)
{
poll_data->timeout_id = 0;
g_main_loop_quit (poll_data->loop);
/* returning FALSE will remove the source id */
return FALSE;
}
/**
* gst_bus_poll:
* @bus: a #GstBus
* @events: a mask of #GstMessageType, representing the set of message types to
* poll for.
* @timeout: the poll timeout, as a #GstClockTimeDiff, or -1 to poll indefinitely.
*
* Poll the bus for events. Will block while waiting for events to come. You can
* specify a maximum time to poll with the @timeout parameter. If @timeout is
* negative, this function will block indefinitely.
*
* Returns: The type of the message that was received, or GST_MESSAGE_UNKNOWN if
* the poll timed out. The message will remain in the bus queue; you will need
* to gst_bus_pop() it off before entering gst_bus_poll() again.
*/
GstMessageType
gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTimeDiff timeout)
{
GstBusPollData *poll_data;
GstMessageType ret;
guint id;
poll_data = g_new0 (GstBusPollData, 1);
if (timeout >= 0)
poll_data->timeout_id = g_timeout_add (timeout / GST_MSECOND,
(GSourceFunc) poll_timeout, poll_data);
poll_data->loop = g_main_loop_new (NULL, FALSE);
poll_data->events = events;
poll_data->revent = GST_MESSAGE_UNKNOWN;
id = gst_bus_add_watch (bus, (GstBusHandler) poll_handler, poll_data);
g_main_loop_run (poll_data->loop);
g_source_remove (id);
ret = poll_data->revent;
if (poll_data->timeout_id)
g_source_remove (poll_data->timeout_id);
g_main_loop_unref (poll_data->loop);
g_free (poll_data);
return ret;
}

View file

@ -24,6 +24,7 @@
#include <gst/gsttypes.h>
#include <gst/gstmessage.h>
#include <gst/gstclock.h>
G_BEGIN_DECLS
@ -51,7 +52,8 @@ struct _GstBus
GstObject object;
/*< private > */
GAsyncQueue *queue;
GQueue *queue;
GMutex *queue_lock;
GstBusSyncHandler sync_handler;
gpointer sync_handler_data;
@ -78,7 +80,7 @@ GstBus* gst_bus_new (void);
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_peek (GstBus * bus);
GstMessage * gst_bus_pop (GstBus * bus);
void gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func,
@ -93,6 +95,9 @@ guint gst_bus_add_watch_full (GstBus * bus,
guint gst_bus_add_watch (GstBus * bus,
GstBusHandler handler,
gpointer user_data);
GstMessageType gst_bus_poll (GstBus *bus, GstMessageType events,
GstClockTimeDiff timeout);
G_END_DECLS
#endif /* __GST_BUS_H__ */

View file

@ -1717,6 +1717,7 @@ void
gst_element_commit_state (GstElement * element)
{
GstElementState pending;
GstMessage *message;
g_return_if_fail (GST_IS_ELEMENT (element));
@ -1735,6 +1736,9 @@ gst_element_commit_state (GstElement * element)
g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
0, old_state, pending);
message = gst_message_new_state_changed (GST_OBJECT (element),
old_state, pending));
gst_element_post_message (element, message);
GST_STATE_BROADCAST (element);
}
}
@ -1753,8 +1757,7 @@ gst_element_commit_state (GstElement * element)
* MT safe.
*/
GstElementStateReturn
gst_element_set_state (GstElement * element, GstElementState state)
{
gst_element_set_state (GstElement * element, GstElementState state) {
GstElementClass *oclass;
GstElementState current;
GstElementStateReturn return_val = GST_STATE_SUCCESS;
@ -1876,7 +1879,7 @@ invalid_return:
* when pads are added to elements?
*/
static gboolean
gst_element_pads_activate (GstElement * element, gboolean active)
gst_element_pads_activate (GstElement * element, gboolean active)
{
GList *pads;
gboolean result;
@ -1967,8 +1970,7 @@ restart:
}
/* is called with STATE_LOCK */
static GstElementStateReturn
gst_element_change_state (GstElement * element)
static GstElementStateReturn gst_element_change_state (GstElement * element)
{
GstElementState old_state;
gint old_pending, old_transition;
@ -2044,16 +2046,14 @@ gst_element_change_state (GstElement * element)
*
* Returns: the #GstElementFactory used for creating this element.
*/
GstElementFactory *
gst_element_get_factory (GstElement * element)
GstElementFactory *gst_element_get_factory (GstElement * element)
{
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
return GST_ELEMENT_GET_CLASS (element)->elementfactory;
}
static void
gst_element_dispose (GObject * object)
static void gst_element_dispose (GObject * object)
{
GstElement *element = GST_ELEMENT (object);
@ -2081,8 +2081,7 @@ gst_element_dispose (GObject * object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_element_finalize (GObject * object)
static void gst_element_finalize (GObject * object)
{
GstElement *element = GST_ELEMENT (object);
@ -2111,13 +2110,14 @@ gst_element_finalize (GObject * object)
* Returns: the new #xmlNodePtr.
*/
static xmlNodePtr
gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
{
GList *pads;
GstElementClass *oclass;
GParamSpec **specs, *spec;
gint nspecs, i;
GValue value = { 0, };
GValue value = {
0,};
GstElement *element;
g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
@ -2187,8 +2187,7 @@ gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
return parent;
}
static void
gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
static void gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
{
xmlNodePtr children;
GstElement *element;
@ -2236,7 +2235,7 @@ gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
#endif /* GST_DISABLE_LOADSAVE */
static void
gst_element_set_manager_func (GstElement * element, GstPipeline * manager)
gst_element_set_manager_func (GstElement * element, GstPipeline * manager)
{
g_return_if_fail (GST_IS_ELEMENT (element));
@ -2249,8 +2248,7 @@ gst_element_set_manager_func (GstElement * element, GstPipeline * manager)
GST_UNLOCK (element);
}
static void
gst_element_set_bus_func (GstElement * element, GstBus * bus)
static void gst_element_set_bus_func (GstElement * element, GstBus * bus)
{
g_return_if_fail (GST_IS_ELEMENT (element));
@ -2263,7 +2261,8 @@ gst_element_set_bus_func (GstElement * element, GstBus * bus)
}
static void
gst_element_set_scheduler_func (GstElement * element, GstScheduler * scheduler)
gst_element_set_scheduler_func (GstElement * element,
GstScheduler * scheduler)
{
g_return_if_fail (GST_IS_ELEMENT (element));
@ -2286,8 +2285,7 @@ gst_element_set_scheduler_func (GstElement * element, GstScheduler * scheduler)
*
* MT safe.
*/
void
gst_element_set_manager (GstElement * element, GstPipeline * manager)
void gst_element_set_manager (GstElement * element, GstPipeline * manager)
{
GstElementClass *oclass;
@ -2310,8 +2308,7 @@ gst_element_set_manager (GstElement * element, GstPipeline * manager)
*
* MT safe.
*/
GstPipeline *
gst_element_get_manager (GstElement * element)
GstPipeline *gst_element_get_manager (GstElement * element)
{
GstPipeline *result = NULL;
@ -2335,8 +2332,7 @@ gst_element_get_manager (GstElement * element)
*
* MT safe.
*/
void
gst_element_set_bus (GstElement * element, GstBus * bus)
void gst_element_set_bus (GstElement * element, GstBus * bus)
{
GstElementClass *oclass;
@ -2358,8 +2354,7 @@ gst_element_set_bus (GstElement * element, GstBus * bus)
*
* MT safe.
*/
GstBus *
gst_element_get_bus (GstElement * element)
GstBus *gst_element_get_bus (GstElement * element)
{
GstBus *result = NULL;
@ -2382,8 +2377,7 @@ gst_element_get_bus (GstElement * element)
*
* MT safe.
*/
void
gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
void gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
{
GstElementClass *oclass;
@ -2405,8 +2399,7 @@ gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
*
* MT safe.
*/
GstScheduler *
gst_element_get_scheduler (GstElement * element)
GstScheduler *gst_element_get_scheduler (GstElement * element)
{
GstScheduler *result = NULL;

View file

@ -247,3 +247,25 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list)
return message;
}
/**
* gst_message_new_state_change:
*
* Create a state change message.
*
* Returns: The new state change message.
*
* MT safe.
*/
GstMessage *
gst_message_new_state_changed (GstObject * src, GstElementState old,
GstElementState new)
{
GstMessage *message;
message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src);
message->message_data.state_changed.old = old;
message->message_data.state_changed.new = new;
return message;
}

View file

@ -32,15 +32,16 @@ G_BEGIN_DECLS 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,
GST_MESSAGE_UNKNOWN = 0,
GST_MESSAGE_EOS = (1 << 0),
GST_MESSAGE_ERROR = (1 << 1),
GST_MESSAGE_WARNING = (1 << 2),
GST_MESSAGE_INFO = (1 << 3),
GST_MESSAGE_TAG = (1 << 4),
GST_MESSAGE_BUFFERING = (1 << 5),
GST_MESSAGE_STATE_CHANGED = (1 << 6),
GST_MESSAGE_STEP_DONE = (1 << 7),
GST_MESSAGE_ANY = 0xffffffff
} GstMessageType;
#define GST_MESSAGE_TRACE_NAME "GstMessage"
@ -62,6 +63,12 @@ typedef enum
#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)
@ -95,6 +102,11 @@ struct _GstMessage
{
GstTagList *list;
} tag;
struct
{
GstElementState old;
GstElementState new;
} state_changed;
} message_data;
/*< private > */
@ -117,6 +129,8 @@ 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);
GstMessage * gst_message_new_state_changed (GstObject * src, GstElementState old,
GstElementState new);
G_END_DECLS
#endif /* __GST_MESSAGE_H__ */

View file

@ -63,7 +63,6 @@ static GstElement *pipeline;
gboolean caught_intr = FALSE;
gboolean caught_error = FALSE;
gboolean tags = FALSE;
GMainLoop *loop;
#ifndef GST_DISABLE_LOADSAVE
@ -159,7 +158,7 @@ fault_handler_sighandler (int signum)
fault_spin ();
}
#else
#else /* USE_SIGINFO */
static void
fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
@ -182,7 +181,7 @@ fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
fault_spin ();
}
#endif
#endif /* USE_SIGINFO */
static void
fault_spin (void)
@ -229,7 +228,7 @@ fault_setup (void)
sigaction (SIGSEGV, &action, NULL);
sigaction (SIGQUIT, &action, NULL);
}
#endif
#endif /* DISABLE_FAULT_HANDLER */
static void
print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
@ -272,15 +271,15 @@ sigint_handler_sighandler (int signum)
}
static gboolean
check_intr (user_data)
check_intr (GstElement * pipeline)
{
if (!caught_intr) {
return TRUE;
} else {
caught_intr = FALSE;
g_print ("Pausing pipeline.\n");
gst_element_set_state (pipeline, GST_STATE_PAUSED);
g_print ("Paused pipeline.\n");
g_main_loop_quit (loop);
return FALSE;
}
}
@ -332,37 +331,67 @@ play_signal_setup (void)
sigaction (SIGUSR1, &action, NULL);
sigaction (SIGUSR2, &action, NULL);
}
#endif
#endif /* DISABLE_FAULT_HANDLER */
static gboolean
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
event_loop (GstElement * pipeline, gboolean blocking)
{
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_TAG:
if (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);
}
break;
case GST_MESSAGE_ERROR:
gst_object_default_error (GST_MESSAGE_SRC (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))
g_main_loop_quit (loop);
break;
default:
break;
}
gst_message_unref (message);
GstBus *bus;
GstMessageType revent;
GstMessage *message = NULL;
GstElementState old, new;
bus = gst_element_get_bus (GST_ELEMENT (pipeline));
g_timeout_add (50, (GSourceFunc) check_intr, pipeline);
while (TRUE) {
revent = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
/* if the poll timed out, only when !blocking */
if (revent == GST_MESSAGE_UNKNOWN)
return FALSE;
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_TAG:
if (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_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));
gst_message_unref (message);
return TRUE;
case GST_MESSAGE_STATE_CHANGED:
GST_MESSAGE_PARSE_STATE_CHANGED (message, &old, &new);
gst_message_unref (message);
if (!(old == GST_STATE_PLAYING && new == GST_STATE_PAUSED))
break;
g_print (_
("Element \"%s\" has gone from PLAYING to PAUSED, quitting.\n"),
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);
break;
}
}
g_assert_not_reached ();
return TRUE;
}
@ -483,12 +512,6 @@ main (int argc, char *argv[])
g_signal_connect (pipeline, "deep_notify",
G_CALLBACK (gst_object_default_deep_notify), exclude_list);
}
loop = g_main_loop_new (NULL, FALSE);
gst_bus_add_watch (gst_element_get_bus (GST_ELEMENT (pipeline)),
(GstBusHandler) message_received, pipeline);
#ifndef GST_DISABLE_LOADSAVE
if (savefile) {
gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
@ -515,7 +538,10 @@ main (int argc, char *argv[])
res = -1;
goto end;
}
gst_element_get_state (pipeline, &state, &pending, NULL);
caught_error = event_loop (pipeline, FALSE);
/* see if we got any messages */
while (g_main_context_iteration (NULL, FALSE));
@ -533,10 +559,8 @@ main (int argc, char *argv[])
goto end;
}
g_timeout_add (50, check_intr, NULL);
g_get_current_time (&tfthen);
g_main_loop_run (loop);
caught_error = event_loop (pipeline, TRUE);
g_get_current_time (&tfnow);
diff = GST_TIMEVAL_TO_TIME (tfnow) - GST_TIMEVAL_TO_TIME (tfthen);