mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
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:
parent
69e9ca3e5f
commit
1a5201826c
7 changed files with 360 additions and 101 deletions
39
ChangeLog
39
ChangeLog
|
@ -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
|
||||
|
|
194
gst/gstbus.c
194
gst/gstbus.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue