- Elements can now send events to their parent.
authorWim Taymans <wim.taymans@gmail.com>
Tue, 18 Dec 2001 19:03:07 +0000 (19:03 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 18 Dec 2001 19:03:07 +0000 (19:03 +0000)
Original commit message from CVS:
- Elements can now send events to their parent.
- remove the g_signals from the core for parent<->child communication
- the application can easily get element info by listening for an event
signal from the toplevel bin.
- added gst_element_info()/_error().
- fakesrc and fakesink use the info event instead of g_print.
- GST_TYPE_* causes segfaults with elect fence, rever to G_TYPE_POINTER
until we know what's wrong.
- various leaks fixed wrt element destroy.
- The object that created the event is now stored as GST_EVENT_SRC

14 files changed:
gst/elements/gstfakesink.c
gst/elements/gstfakesrc.c
gst/gstbin.c
gst/gstelement.c
gst/gstelement.h
gst/gstevent.c
gst/gstevent.h
gst/gstpad.c
gst/gstpad.h
gst/gstqueue.c
gst/gsttypes.h
plugins/elements/gstfakesink.c
plugins/elements/gstfakesrc.c
plugins/elements/gstqueue.c

index 59a61b9..8c07e25 100644 (file)
@@ -226,9 +226,10 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
   }
   */
 
-  if (!fakesink->silent)
-    g_print("fakesink: chain   ******* (%s:%s)< (%d bytes, %lld) %p\n",
+  if (!fakesink->silent) { 
+    gst_element_info (GST_ELEMENT (fakesink), "chain   ******* (%s:%s)< (%d bytes, %lld) %p",
                GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
+  }
 
   g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
 
index 5cc4368..7d8d6e3 100644 (file)
@@ -300,6 +300,8 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
   srcpad = gst_pad_new_from_template (templ, name);
   gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
 
+  g_free (name);
+
   return srcpad;
 }
 
@@ -312,7 +314,6 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
-      g_print("fakesrc: have seek event\n");
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
       if (!GST_EVENT_SEEK_FLUSH (event)) {
         gst_event_free (event);
@@ -320,11 +321,9 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
       }
       /* else we do a flush too */
     case GST_EVENT_FLUSH:
-      g_print("fakesrc: have flush event\n");
       src->need_flush = TRUE;
       break;
     default:
-      g_print("fakesrc: have unhandled event\n");
       break;
   }
 
@@ -646,12 +645,10 @@ gst_fakesrc_get(GstPad *pad)
 
   if (src->need_flush) {
     src->need_flush = FALSE;
-    g_print("fakesrc: sending FLUSH\n");
     return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
   }
 
   if (src->rt_num_buffers == 0) {
-    g_print("fakesrc: sending EOS\n");
     gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
   }
@@ -662,16 +659,17 @@ gst_fakesrc_get(GstPad *pad)
 
   if (src->eos) {
     GST_INFO (0, "fakesrc is setting eos on pad");
-    g_print("fakesrc: sending EOS\n");
     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
   }
 
   buf = gst_fakesrc_create_buffer (src);
   GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
 
-  if (!src->silent)
-    g_print("fakesrc: get      ******* (%s:%s)> (%d bytes, %llu) \n",
-               GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+  if (!src->silent) {
+    gst_element_info (GST_ELEMENT (src), 
+                     "get      ******* (%s:%s)> (%d bytes, %llu)",
+                      GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+  }
 
   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit\n");
   g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
@@ -715,7 +713,6 @@ gst_fakesrc_loop(GstElement *element)
       }
 
       if (src->eos) {
-        GST_INFO (0, "fakesrc is setting eos on pad");
         gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
        return;
       }
@@ -723,9 +720,10 @@ gst_fakesrc_loop(GstElement *element)
       buf = gst_fakesrc_create_buffer (src);
       GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
 
-      if (!src->silent)
-        g_print("fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu) \n",
-               GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+      if (!src->silent) {
+        gst_element_info (element, "fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu)",
+                            GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+      }
 
       g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
                        buf, pad);
@@ -768,9 +766,6 @@ gst_fakesrc_change_state (GstElement *element)
       break;
   }
 
-  if (GST_STATE_PENDING (element) == GST_STATE_READY) {
-  }
-
   if (GST_ELEMENT_CLASS (parent_class)->change_state)
     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
 
index 4258aa9..d697b47 100644 (file)
@@ -23,6 +23,7 @@
 /* #define GST_DEBUG_ENABLED */
 #include "gst_private.h"
 
+#include "gstevent.h"
 #include "gstbin.h"
 
 #include "gstscheduler.h"
@@ -40,11 +41,14 @@ GType _gst_bin_type = 0;
 
 static void                    gst_bin_dispose                 (GObject * object);
 
-static GstElementStateReturn   gst_bin_change_state            (GstElement * element);
-static GstElementStateReturn   gst_bin_change_state_norecurse  (GstBin * bin);
-static gboolean                gst_bin_change_state_type       (GstBin * bin, GstElementState state, GType type);
-static void                    gst_bin_child_state_change      (GstBin * bin, GstElementState old,
-                                                                GstElementState new, GstElement * element);
+static GstElementStateReturn   gst_bin_change_state            (GstElement *element);
+static GstElementStateReturn   gst_bin_change_state_norecurse  (GstBin *bin);
+static gboolean                        gst_bin_change_state_type       (GstBin *bin,
+                                                                GstElementState state,
+                                                                GType type);
+static void                    gst_bin_child_state_change      (GstBin *bin, GstElementState old, 
+                                                                GstElementState new, GstElement *child);
+static void                    gst_bin_send_event              (GstElement *element, GstEvent *event);
 
 static gboolean                gst_bin_iterate_func            (GstBin * bin);
 
@@ -110,7 +114,10 @@ gst_bin_class_init (GstBinClass * klass)
   gst_bin_signals[OBJECT_ADDED] =
     g_signal_new ("object_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GstBinClass, object_added), NULL, NULL,
-                 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
+                 gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+  klass->change_state_type =           GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
+  klass->iterate =                     GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
 
   gobject_class->dispose               = GST_DEBUG_FUNCPTR (gst_bin_dispose);
 #ifndef GST_DISABLE_LOADSAVE
@@ -119,6 +126,7 @@ gst_bin_class_init (GstBinClass * klass)
 #endif
 
   gstelement_class->change_state       = GST_DEBUG_FUNCPTR (gst_bin_change_state);
+  gstelement_class->send_event                 = GST_DEBUG_FUNCPTR (gst_bin_send_event);
 
   klass->change_state_type             = GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
   klass->iterate                       = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
@@ -272,8 +280,6 @@ gst_bin_add (GstBin * bin, GstElement * element)
 
   /* set the element's parent and add the element to the bin's list of children */
   gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
-  g_signal_connect_swapped (G_OBJECT (element), "state_change",
-                           G_CALLBACK (gst_bin_child_state_change), G_OBJECT (bin));
 
   bin->children = g_list_append (bin->children, element);
   bin->numchildren++;
@@ -384,10 +390,33 @@ gst_bin_child_state_change (GstBin * bin, GstElementState old, GstElementState n
       break;
     }
   }
-
   GST_UNLOCK (bin);
 }
 
+static void
+gst_bin_send_event (GstElement *element, GstEvent *event)
+{
+  GST_DEBUG (GST_CAT_EVENT, "event from %s in %s\n", 
+          gst_element_get_name (GST_ELEMENT (GST_EVENT_SRC (event))),
+          gst_element_get_name (element));
+
+  if (GST_ELEMENT (GST_EVENT_SRC (event)) == element) {
+    GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
+    return;
+  }
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_STATE_CHANGE:
+      gst_bin_child_state_change (GST_BIN (element), GST_EVENT_STATE_OLD (event),
+                                 GST_EVENT_STATE_NEW (event), GST_ELEMENT (GST_EVENT_SRC (event)));
+      gst_event_free (event);
+      break;
+    default:
+      GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
+      break;
+  }
+}
+
 static GstElementStateReturn
 gst_bin_change_state (GstElement * element)
 {
@@ -432,8 +461,10 @@ gst_bin_change_state (GstElement * element)
     }
   }
 
-  GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s",
-                   gst_element_statename (old_state), gst_element_statename (pending));
+  GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s, now in %s",
+                gst_element_statename (old_state),
+                gst_element_statename (pending),
+                gst_element_statename (GST_STATE (element)));
 
   if (have_async)
     ret = GST_STATE_ASYNC;
index 028a809..6be17a4 100644 (file)
@@ -29,6 +29,7 @@
 #include "gstextratypes.h"
 #include "gstbin.h"
 #include "gstscheduler.h"
+#include "gstevent.h"
 #include "gstutils.h"
 
 /* Element signals and args */
@@ -37,6 +38,7 @@ enum {
   NEW_PAD,
   PAD_REMOVED,
   ERROR,
+  EVENT,
   EOS,
   LAST_SIGNAL
 };
@@ -59,6 +61,7 @@ static void                   gst_element_get_property        (GObject *object, guint prop_id, GValue *
 static void                    gst_element_dispose             (GObject *object);
 
 static GstElementStateReturn   gst_element_change_state        (GstElement *element);
+static void                    gst_element_send_event_func     (GstElement *element, GstEvent *event);
 
 #ifndef GST_DISABLE_LOADSAVE
 static xmlNodePtr              gst_element_save_thyself        (GstObject *object, xmlNodePtr parent);
@@ -102,27 +105,32 @@ gst_element_class_init (GstElementClass *klass)
   parent_class = g_type_class_ref(GST_TYPE_OBJECT);
 
   gst_element_signals[STATE_CHANGE] =
-    g_signal_new ("state_change", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+    g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
                  gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
                   G_TYPE_INT, G_TYPE_INT);
   gst_element_signals[NEW_PAD] =
-    g_signal_new ("new_pad", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+    g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
-                  gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
-                  GST_TYPE_PAD);
+                  gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+                  G_TYPE_POINTER);
   gst_element_signals[PAD_REMOVED] =
-    g_signal_new ("pad_removed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+    g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
-                  gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
-                   GST_TYPE_PAD);
+                  gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+                  G_TYPE_POINTER);
   gst_element_signals[ERROR] =
-    g_signal_new ("error", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+    g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
                   gst_marshal_VOID__STRING, G_TYPE_NONE,1,
-                   G_TYPE_STRING);
+                  G_TYPE_STRING);
+  gst_element_signals[EVENT] =
+    g_signal_new ("event", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GstElementClass, event), NULL, NULL,
+                  gst_marshal_VOID__POINTER, G_TYPE_NONE,1,
+                  G_TYPE_POINTER);
   gst_element_signals[EOS] =
-    g_signal_new ("eos", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+    g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
                   gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
@@ -138,9 +146,10 @@ gst_element_class_init (GstElementClass *klass)
 #endif
 
   klass->change_state                  = GST_DEBUG_FUNCPTR (gst_element_change_state);
-  klass->elementfactory        = NULL;
-  klass->padtemplates          = NULL;
-  klass->numpadtemplates       = 0;
+  klass->send_event                    = GST_DEBUG_FUNCPTR (gst_element_send_event_func);
+  klass->elementfactory                = NULL;
+  klass->padtemplates                  = NULL;
+  klass->numpadtemplates               = 0;
 }
 
 static void
@@ -158,7 +167,7 @@ static void
 gst_element_init (GstElement *element)
 {
   element->current_state = GST_STATE_NULL;
-  element->pending_state = -1;
+  element->pending_state = GST_STATE_VOID_PENDING;
   element->numpads = 0;
   element->numsrcpads = 0;
   element->numsinkpads = 0;
@@ -166,6 +175,8 @@ gst_element_init (GstElement *element)
   element->loopfunc = NULL;
   element->threadstate = NULL;
   element->sched = NULL;
+  element->state_mutex = g_mutex_new ();
+  element->state_cond = g_cond_new ();
 }
 
 
@@ -760,6 +771,21 @@ gst_element_disconnect (GstElement *src, const gchar *srcpadname,
   gst_pad_disconnect(srcpad,destpad);
 }
 
+static void
+gst_element_message (GstElement *element, const gchar *type, const gchar *info, va_list var_args)
+{
+  GstEvent *event;
+  GstProps *props;
+  gchar *string;
+  
+  string = g_strdup_vprintf (info, var_args);
+
+  event = gst_event_new_info (type, GST_PROPS_STRING (string), NULL);
+  gst_element_send_event (element, event);
+
+  g_free (string);
+}
+
 /**
  * gst_element_error:
  * @element: Element with the error
@@ -769,15 +795,75 @@ gst_element_disconnect (GstElement *src, const gchar *srcpadname,
  * condition.  It results in the "error" signal.
  */
 void
-gst_element_error (GstElement *element, const gchar *error)
+gst_element_error (GstElement *element, const gchar *error, ...)
 {
-  g_error("GstElement: error in element '%s': %s\n", GST_ELEMENT_NAME(element), error);
+  va_list var_args;
+  
+  va_start (var_args, error);
+  gst_element_message (element, "error", error, var_args);
+  va_end (var_args);
+}
+
+/**
+ * gst_element_info:
+ * @element: Element with the info
+ * @info: String describing the info
+ *
+ * This function is used internally by elements to signal an info
+ * condition.  It results in the "info" signal.
+ */
+void
+gst_element_info (GstElement *element, const gchar *info, ...)
+{
+  va_list var_args;
+  
+  va_start (var_args, info);
+  gst_element_message (element, "info", info, var_args);
+  va_end (var_args);
+}
 
-  /* FIXME: this is not finished!!! */
 
-  g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, error);
+static void
+gst_element_send_event_func (GstElement *element, GstEvent *event)
+{
+  if (GST_OBJECT_PARENT (element)) {
+    gst_element_send_event (GST_ELEMENT (GST_OBJECT_PARENT (element)), event);
+  }
+  else {
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_STATE_CHANGE:
+        g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0, 
+                       GST_EVENT_STATE_OLD (event), GST_EVENT_STATE_NEW (event));
+      default:
+        g_signal_emit (G_OBJECT (element), gst_element_signals[EVENT], 0, event);
+    }
+    gst_event_free (event);
+  }
 }
 
+/**
+ * gst_element_send_event:
+ * @element: Element generating the event
+ * @event: the event to send
+ *
+ * This function is used intenally by elements to send an event to 
+ * the app. It will result in an "event" signal.
+ */
+void
+gst_element_send_event (GstElement *element, GstEvent *event)
+{
+  GstElementClass *oclass = (GstElementClass *) G_OBJECT_GET_CLASS (element);
+
+  g_return_if_fail (GST_IS_ELEMENT (element));
+  g_return_if_fail (event);
+
+  if (GST_EVENT_SRC (event) == NULL)
+    GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (element));
+
+  if (oclass->send_event)
+    (oclass->send_event) (element, event);
+
+}
 
 /**
  * gst_element_get_state:
@@ -795,13 +881,6 @@ gst_element_get_state (GstElement *element)
   return GST_STATE (element);
 }
 
-static void
-gst_element_wait_done (GstElement *element, GstElementState old, GstElementState new, GCond *cond)
-{
-  g_signal_handlers_disconnect_by_func (G_OBJECT (element), gst_element_wait_done, cond);
-  g_cond_signal (cond);
-}
-
 /**
  * gst_element_wait_state_change:
  * @element: element wait for
@@ -811,17 +890,9 @@ gst_element_wait_done (GstElement *element, GstElementState old, GstElementState
 void
 gst_element_wait_state_change (GstElement *element)
 {
-  GCond *cond = g_cond_new ();
-  GMutex *mutex = g_mutex_new ();
-
-  g_mutex_lock (mutex);
-  g_signal_connect (G_OBJECT (element), "state_change",
-                   G_CALLBACK (gst_element_wait_done), cond);
-  g_cond_wait (cond, mutex);
-  g_mutex_unlock (mutex);
-
-  g_mutex_free (mutex);
-  g_cond_free (cond);
+  g_mutex_lock (element->state_mutex);
+  g_cond_wait (element->state_cond, element->state_mutex);
+  g_mutex_unlock (element->state_mutex);
 }
 /**
  * gst_element_set_state:
@@ -935,14 +1006,15 @@ gst_element_change_state (GstElement *element)
   GST_STATE (element) = GST_STATE_PENDING (element);
   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
 
-  /* note: queues' state_change is a special case because it needs to lock
-   * for synchronization (from another thread).  since this signal may block
-   * or (worse) make another state change, the queue needs to unlock before
-   * calling.  thus, gstqueue.c::gst_queue_state_change() blocks, unblocks,
-   * unlocks, then emits this. 
-   */
-  g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0,
-                   old_state, GST_STATE (element));
+  g_mutex_lock (element->state_mutex);
+  g_cond_signal (element->state_cond);
+  g_mutex_unlock (element->state_mutex);
+
+  {
+    GstEvent *event = gst_event_new_state_change (old_state, GST_STATE (element));
+
+    gst_element_send_event (element, event);
+  }
 
   return GST_STATE_SUCCESS;
 }
@@ -995,6 +1067,8 @@ gst_element_dispose (GObject *object)
   element->numsrcpads = 0;
   element->numsinkpads = 0;
   element->numpads = 0;
+  g_mutex_free (element->state_mutex);
+  g_cond_free (element->state_cond);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
index 4f48140..3e80f40 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <gst/gstconfig.h>
 
+#include <gst/gsttypes.h>
 #include <gst/gstobject.h>
 #include <gst/gstpad.h>
 #include <gst/cothreads.h>
@@ -37,20 +38,23 @@ extern "C" {
 
 #define GST_NUM_STATES 4
 
-typedef enum {
-  GST_STATE_VOID_PENDING       = 0,
-  GST_STATE_NULL               = (1 << 0),
-  GST_STATE_READY              = (1 << 1),
-  GST_STATE_PAUSED             = (1 << 2),
-  GST_STATE_PLAYING            = (1 << 3),
-} GstElementState;
+//typedef enum _GstElementState GstElementState;
+//typedef enum _GstElementStateReturn GstElementStateReturn;
 
-typedef enum {
-  GST_STATE_FAILURE            = 0,
-  GST_STATE_SUCCESS            = 1,
-  GST_STATE_ASYNC              = 2,
-} GstElementStateReturn;
 
+enum _GstElementState {
+  GST_STATE_VOID_PENDING        = 0,
+  GST_STATE_NULL                = (1 << 0),
+  GST_STATE_READY               = (1 << 1),
+  GST_STATE_PAUSED              = (1 << 2),
+  GST_STATE_PLAYING             = (1 << 3),
+};
+
+enum _GstElementStateReturn {
+  GST_STATE_FAILURE             = 0,
+  GST_STATE_SUCCESS             = 1,
+  GST_STATE_ASYNC               = 2,
+};
 
 /* NOTE: this probably should be done with an #ifdef to decide 
  * whether to safe-cast or to just do the non-checking cast.
@@ -150,6 +154,9 @@ struct _GstElement {
   guint16              numsinkpads;
   GList                *pads;
   GstPad               *select_pad;
+
+  GMutex               *state_mutex;
+  GCond                *state_cond;
 };
 
 struct _GstElementClass {
@@ -166,16 +173,19 @@ struct _GstElementClass {
   void (*new_pad)              (GstElement *element, GstPad *pad);
   void (*pad_removed)          (GstElement *element, GstPad *pad);
   void (*error)                        (GstElement *element, gchar *error);
+  void (*event)                        (GstElement *element, GstEvent *event);
   void (*eos)                  (GstElement *element);
 
   /* local pointers for get/set */
   void (*set_property)         (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
   void (*get_property) (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
+  /* vtable*/
   /* change the element state */
   GstElementStateReturn (*change_state)                (GstElement *element);
   /* request a new pad */
   GstPad*              (*request_new_pad)      (GstElement *element, GstPadTemplate *templ, const gchar* name);
+  void                 (*send_event)           (GstElement *element, GstEvent *event);
 };
 
 void                   gst_element_class_add_padtemplate       (GstElementClass *klass, GstPadTemplate *templ);
@@ -214,6 +224,8 @@ void                        gst_element_disconnect          (GstElement *src, const gchar *srcpadname,
 
 void                   gst_element_signal_eos          (GstElement *element);
 
+void                   gst_element_send_event          (GstElement *element, GstEvent *event);
+
 
 GstElementState         gst_element_get_state           (GstElement *element);
 gint                   gst_element_set_state           (GstElement *element, GstElementState state);
@@ -222,7 +234,8 @@ void                        gst_element_wait_state_change   (GstElement *element);
        
 const gchar*           gst_element_statename           (GstElementState state);
 
-void                   gst_element_error               (GstElement *element, const gchar *error);
+void                   gst_element_info                (GstElement *element, const gchar *info, ...);
+void                   gst_element_error               (GstElement *element, const gchar *error, ...);
 
 GstElementFactory*     gst_element_get_factory         (GstElement *element);
 
index 8607cdc..2a3ff74 100644 (file)
@@ -77,6 +77,8 @@ gst_event_new (GstEventType type)
 
   GST_DATA_TYPE (event) = _gst_event_type;
   GST_EVENT_TYPE (event) = type;
+  GST_EVENT_TIMESTAMP (event) = 0LL;
+  GST_EVENT_SRC (event) = NULL;
 
   return event;
 }
@@ -91,6 +93,16 @@ void
 gst_event_free (GstEvent* event)
 {
   g_mutex_lock (_gst_event_chunk_lock);
+  if (GST_EVENT_SRC (event)) {
+    gst_object_unref (GST_EVENT_SRC (event));
+  }
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_INFO:
+      gst_props_unref (GST_EVENT_INFO_PROPS (event));
+      break;
+    default:
+      break;
+  }
   g_mem_chunk_free (_gst_event_chunk, event);
   g_mutex_unlock (_gst_event_chunk_lock);
 }
@@ -117,3 +129,49 @@ gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush)
 
   return event;
 }
+
+/**
+ * gst_event_new_info:
+ * @props: The GstProps for this info event
+ *
+ * Allocate a new info event with the given props.
+ *
+ * Returns: A new info event.
+ */
+GstEvent*       
+gst_event_new_info (const gchar *firstname, ...)
+{
+  GstEvent *event;
+  va_list var_args;
+      
+  event = gst_event_new (GST_EVENT_INFO);
+  va_start (var_args, firstname); 
+
+  GST_EVENT_INFO_PROPS (event) = gst_props_newv (firstname, var_args);
+         
+  va_end (var_args);
+
+  return event;
+}
+/**
+ * gst_event_new_state_change:
+ * @old: The old state
+ * @state: The new state
+ *
+ * Allocate a new state change event with the given props.
+ *
+ * Returns: A new state change event.
+ */
+GstEvent*       
+gst_event_new_state_change (GstElementState old, GstElementState state)
+{
+  GstEvent *event;
+
+  event = gst_event_new (GST_EVENT_STATE_CHANGE);
+  GST_EVENT_STATE_OLD (event) = old;
+  GST_EVENT_STATE_NEW (event) = state;
+
+  return event;
+}
+
+
index 2e45b2b..c1f35f2 100644 (file)
 #ifndef __GST_EVENT_H__
 #define __GST_EVENT_H__
 
+#include <gst/gsttypes.h>
+#include <gst/gstelement.h>
 #include <gst/gstobject.h>
 #include <gst/gstdata.h>
+#include <gst/gstcaps.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -33,11 +36,16 @@ extern "C" {
 
 typedef enum {
   GST_EVENT_UNKNOWN,
+  /* horizontal events */
   GST_EVENT_EOS,
   GST_EVENT_FLUSH,
   GST_EVENT_EMPTY,
   GST_EVENT_SEEK,
-  GST_EVENT_DISCONTINUOUS
+  GST_EVENT_DISCONTINUOUS,
+  /* vertical events */
+  GST_EVENT_INFO,
+  GST_EVENT_ERROR,
+  GST_EVENT_STATE_CHANGE,
 } GstEventType;
 
 extern GType _gst_event_type;
@@ -47,7 +55,8 @@ extern GType _gst_event_type;
 #define GST_IS_EVENT(event)    (GST_DATA_TYPE(event) == GST_TYPE_EVENT)
 
 #define GST_EVENT_TYPE(event)          (GST_EVENT(event)->type)
-#define GST_EVENT_TIMESTAMP(event)     (GST_EVENT(event)->timstamp)
+#define GST_EVENT_TIMESTAMP(event)     (GST_EVENT(event)->timestamp)
+#define GST_EVENT_SRC(event)           (GST_EVENT(event)->src)
 
 /* seek events */
 typedef enum {
@@ -60,13 +69,18 @@ typedef enum {
 #define GST_EVENT_SEEK_OFFSET(event)   (GST_EVENT(event)->event_data.seek.offset)
 #define GST_EVENT_SEEK_FLUSH(event)    (GST_EVENT(event)->event_data.seek.flush)
 
-typedef struct _GstEvent GstEvent;
+#define GST_EVENT_INFO_PROPS(event)    (GST_EVENT(event)->event_data.info.props)
+
+#define GST_EVENT_STATE_OLD(event)     (GST_EVENT(event)->event_data.state.old_state)
+#define GST_EVENT_STATE_NEW(event)     (GST_EVENT(event)->event_data.state.new_state)
+
 
 struct _GstEvent {
   GstData data;
 
   GstEventType  type;
   guint64      timestamp;
+  GstObject    *src;
 
   union {
     struct {
@@ -74,6 +88,13 @@ struct _GstEvent {
       guint64     offset;
       gboolean   flush;
     } seek;
+    struct {
+      GstProps *props;
+    } info;
+    struct {
+      GstElementState old_state;
+      GstElementState new_state;
+    } state;
   } event_data;
 };
 
@@ -88,6 +109,12 @@ GstEvent*   gst_event_new_seek      (GstSeekType type, guint64 offset, gboolean flush);
 /* flush events */
 #define                gst_event_new_flush()   gst_event_new(GST_EVENT_FLUSH)
 
+/* info events */
+GstEvent*      gst_event_new_info      (const gchar *firstname, ...);
+
+/* state change events */
+GstEvent*      gst_event_new_state_change (GstElementState old, GstElementState state);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index f2d3191..1308b18 100644 (file)
@@ -29,6 +29,7 @@
 #include "gsttype.h"
 #include "gstbin.h"
 #include "gstscheduler.h"
+#include "gstevent.h"
 
 GType _gst_pad_type = 0;
 
@@ -1671,8 +1672,8 @@ gst_padtemplate_class_init (GstPadTemplateClass *klass)
   gst_padtemplate_signals[TEMPL_PAD_CREATED] =
     g_signal_new ("pad_created", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
                     G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), NULL, NULL,
-                    gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
-                    GST_TYPE_PAD);
+                    gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+                    G_TYPE_POINTER);
 
 
   gstobject_class->path_string_separator = "*";
@@ -1969,6 +1970,7 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
   GstElement *element = GST_PAD_PARENT (pad);
  
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH:
     case GST_EVENT_EOS:
 /*      gst_element_signal_eos (element); */
       gst_element_set_state (element, GST_STATE_PAUSED);
@@ -2006,6 +2008,9 @@ gst_pad_send_event (GstPad *pad, GstEvent *event)
 
   g_return_val_if_fail (event, FALSE);
 
+  if (GST_EVENT_SRC (event) == NULL)
+    GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
+
   GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
                  GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
 
index d2f6653..b9f61cb 100644 (file)
@@ -30,7 +30,6 @@
 #include <gst/gstbuffer.h>
 #include <gst/cothreads.h>
 #include <gst/gstcaps.h>
-#include <gst/gstevent.h>
 
 
 #ifdef __cplusplus
index 23482d7..4561fa6 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "gstqueue.h"
 #include "gstscheduler.h"
+#include "gstevent.h"
 
 GstElementDetails gst_queue_details = {
   "Queue",
index e6f0335..b169ba7 100644 (file)
@@ -13,5 +13,9 @@ typedef struct _GstBin GstBin;
 typedef struct _GstBinClass GstBinClass;
 typedef struct _GstScheduler GstScheduler;
 typedef struct _GstSchedulerClass GstSchedulerClass;
+typedef struct _GstEvent GstEvent;
+
+typedef enum _GstElementState GstElementState;
+typedef enum _GstElementStateReturn GstElementStateReturn;
 
 #endif
index 59a61b9..8c07e25 100644 (file)
@@ -226,9 +226,10 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
   }
   */
 
-  if (!fakesink->silent)
-    g_print("fakesink: chain   ******* (%s:%s)< (%d bytes, %lld) %p\n",
+  if (!fakesink->silent) { 
+    gst_element_info (GST_ELEMENT (fakesink), "chain   ******* (%s:%s)< (%d bytes, %lld) %p",
                GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
+  }
 
   g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
 
index 5cc4368..7d8d6e3 100644 (file)
@@ -300,6 +300,8 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
   srcpad = gst_pad_new_from_template (templ, name);
   gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
 
+  g_free (name);
+
   return srcpad;
 }
 
@@ -312,7 +314,6 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
-      g_print("fakesrc: have seek event\n");
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
       if (!GST_EVENT_SEEK_FLUSH (event)) {
         gst_event_free (event);
@@ -320,11 +321,9 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
       }
       /* else we do a flush too */
     case GST_EVENT_FLUSH:
-      g_print("fakesrc: have flush event\n");
       src->need_flush = TRUE;
       break;
     default:
-      g_print("fakesrc: have unhandled event\n");
       break;
   }
 
@@ -646,12 +645,10 @@ gst_fakesrc_get(GstPad *pad)
 
   if (src->need_flush) {
     src->need_flush = FALSE;
-    g_print("fakesrc: sending FLUSH\n");
     return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
   }
 
   if (src->rt_num_buffers == 0) {
-    g_print("fakesrc: sending EOS\n");
     gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
   }
@@ -662,16 +659,17 @@ gst_fakesrc_get(GstPad *pad)
 
   if (src->eos) {
     GST_INFO (0, "fakesrc is setting eos on pad");
-    g_print("fakesrc: sending EOS\n");
     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
   }
 
   buf = gst_fakesrc_create_buffer (src);
   GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
 
-  if (!src->silent)
-    g_print("fakesrc: get      ******* (%s:%s)> (%d bytes, %llu) \n",
-               GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+  if (!src->silent) {
+    gst_element_info (GST_ELEMENT (src), 
+                     "get      ******* (%s:%s)> (%d bytes, %llu)",
+                      GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+  }
 
   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit\n");
   g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
@@ -715,7 +713,6 @@ gst_fakesrc_loop(GstElement *element)
       }
 
       if (src->eos) {
-        GST_INFO (0, "fakesrc is setting eos on pad");
         gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
        return;
       }
@@ -723,9 +720,10 @@ gst_fakesrc_loop(GstElement *element)
       buf = gst_fakesrc_create_buffer (src);
       GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
 
-      if (!src->silent)
-        g_print("fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu) \n",
-               GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+      if (!src->silent) {
+        gst_element_info (element, "fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu)",
+                            GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+      }
 
       g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
                        buf, pad);
@@ -768,9 +766,6 @@ gst_fakesrc_change_state (GstElement *element)
       break;
   }
 
-  if (GST_STATE_PENDING (element) == GST_STATE_READY) {
-  }
-
   if (GST_ELEMENT_CLASS (parent_class)->change_state)
     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
 
index 23482d7..4561fa6 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "gstqueue.h"
 #include "gstscheduler.h"
+#include "gstevent.h"
 
 GstElementDetails gst_queue_details = {
   "Queue",