- Remove the propsprivate header file
authorWim Taymans <wim.taymans@gmail.com>
Sat, 30 Mar 2002 17:05:03 +0000 (17:05 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sat, 30 Mar 2002 17:05:03 +0000 (17:05 +0000)
Original commit message from CVS:
- Remove the propsprivate header file
- Added new API for properties.
- Moved the clock distribution to the scheduler.
- Removed the lock from GstCaps
- Added boxed types for Caps/Props
- Simplified the clock, new systemclock implementation
- Removed deprecated element_info/send_event functions
- First step at exposing more info in the pad_connect functions
- Queue cleanup
- Make the scheduler aware of other schedulers inside it
- Added the _SELF_SCHEDULABLE flag to gstthread
- Removed _get_widget from _utils, changed to new props API
- Make fakesink sync on timestamps when requested
- Removed the offset notify from filesrc
- Added a fast scheduler
- some scheduler cleanups.

39 files changed:
gst/Makefile.am
gst/elements/gstfakesink.c
gst/elements/gstfakesink.h
gst/elements/gstfakesrc.c
gst/elements/gstfakesrc.h
gst/elements/gstfilesrc.c
gst/elements/gsttee.c
gst/gst.h
gst/gstbin.c
gst/gstbin.h
gst/gstcaps.c
gst/gstcaps.h
gst/gstclock.c
gst/gstclock.h
gst/gstelement.c
gst/gstelement.h
gst/gstpad.c
gst/gstpad.h
gst/gstprops.c
gst/gstprops.h
gst/gstpropsprivate.h [deleted file]
gst/gstqueue.c
gst/gstscheduler.c
gst/gstscheduler.h
gst/gstsystemclock.c
gst/gstsystemclock.h
gst/gstthread.c
gst/gstutils.c
gst/gstutils.h
gst/schedulers/Makefile.am
gst/schedulers/gstbasicscheduler.c
gst/schedulers/gstfastscheduler.c [new file with mode: 0644]
plugins/elements/gstfakesink.c
plugins/elements/gstfakesink.h
plugins/elements/gstfakesrc.c
plugins/elements/gstfakesrc.h
plugins/elements/gstfilesrc.c
plugins/elements/gstqueue.c
plugins/elements/gsttee.c

index f802393..ac40feb 100644 (file)
@@ -145,19 +145,18 @@ libgstreamerinclude_HEADERS =             \
 noinst_HEADERS =       \
        gst_private.h   \
        gstarch.h       \
-       gstpropsprivate.h \
        cothreads.h
 
 libgstreamer_la_CFLAGS = -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" \
        $(LIBGST_CFLAGS) \
        -D_GNU_SOURCE \
        -DG_LOG_DOMAIN=g_log_domain_gstreamer \
-       -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\"
+       -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" 
 
 # the compiler shoots cothreads.c in the head at -O6
-libcothreads_la_CFLAGS = $(libgstreamer_la_CFLAGS) -O2
+libcothreads_la_CFLAGS = $(libgstreamer_la_CFLAGS) -O2 
 
 libgstreamer_la_LIBADD = $(LIBGST_LIBS)
-libgstreamer_la_LDFLAGS = @GST_LT_LDFLAGS@ -version-info @GST_LIBVERSION@
+libgstreamer_la_LDFLAGS = @GST_LT_LDFLAGS@ -version-info @GST_LIBVERSION@ 
 
 EXTRA_DIST = ROADMAP
index c6d0198..21f4c92 100644 (file)
@@ -46,6 +46,7 @@ enum {
   ARG_NUM_SINKS,
   ARG_SILENT,
   ARG_DUMP,
+  ARG_SYNC,
   ARG_LAST_MESSAGE,
 };
 
@@ -60,6 +61,7 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
 static void    gst_fakesink_class_init         (GstFakeSinkClass *klass);
 static void    gst_fakesink_init               (GstFakeSink *fakesink);
 
+static void    gst_fakesink_set_clock          (GstElement *element, GstClock *clock);
 static GstPad*         gst_fakesink_request_new_pad    (GstElement *element, GstPadTemplate *templ, const
                                                  gchar *unused);
 
@@ -106,12 +108,14 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SINKS,
-    g_param_spec_int ("num_sinks", "num_sinks", "num_sinks",
+    g_param_spec_int ("num_sinks", "Number of sinks", "The number of sinkpads",
                       1, G_MAXINT, 1, G_PARAM_READABLE)); 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
     g_param_spec_string ("last_message", "last_message", "last_message",
                          NULL, G_PARAM_READABLE));
-
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SYNC,
+    g_param_spec_boolean("sync","Sync","Sync on the clock",
+                         FALSE, G_PARAM_READWRITE)); /* CHECKME */
 
   gst_element_class_install_std_props (
          GST_ELEMENT_CLASS (klass),
@@ -141,9 +145,22 @@ gst_fakesink_init (GstFakeSink *fakesink)
 
   fakesink->silent = FALSE;
   fakesink->dump = FALSE;
+  fakesink->sync = FALSE;
   fakesink->last_message = NULL;
+
+  GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
 }
 
+static void
+gst_fakesink_set_clock (GstElement *element, GstClock *clock)
+{ 
+  GstFakeSink *sink;
+
+  sink = GST_FAKESINK (element);
+
+  sink->clock = clock;
+} 
+
 static GstPad*
 gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
 {
@@ -183,6 +200,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
     case ARG_DUMP:
       sink->dump = g_value_get_boolean (value);
       break;
+    case ARG_SYNC:
+      sink->sync = g_value_get_boolean (value);
+      break;
     default:
       break;
   }
@@ -208,6 +228,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
     case ARG_DUMP:
       g_value_set_boolean (value, sink->dump);
       break;
+    case ARG_SYNC:
+      g_value_set_boolean (value, sink->sync);
+      break;
     case ARG_LAST_MESSAGE:
       g_value_set_string (value, sink->last_message);
       break;
@@ -228,9 +251,12 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
 
   fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
 
+  if (fakesink->sync) { 
+    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
+  }
+
   if (!fakesink->silent) { 
-    if (fakesink->last_message) 
-      g_free (fakesink->last_message);
+    g_free (fakesink->last_message);
 
     fakesink->last_message = g_strdup_printf ("chain   ******* (%s:%s)< (%d bytes, %lld) %p",
                GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
index 4bc3bb5..6c38ae3 100644 (file)
@@ -52,11 +52,14 @@ typedef struct _GstFakeSink GstFakeSink;
 typedef struct _GstFakeSinkClass GstFakeSinkClass;
 
 struct _GstFakeSink {
-  GstElement element;
+  GstElement    element;
 
-  gboolean silent;
-  gboolean dump;
-  gchar    *last_message;
+  gboolean      silent;
+  gboolean      dump;
+  gboolean      sync;
+  GstClock     *clock;
+
+  gchar        *last_message;
 };
 
 struct _GstFakeSinkClass {
index 18ef726..9686385 100644 (file)
@@ -321,6 +321,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
+
       if (!GST_EVENT_SEEK_FLUSH (event)) {
         gst_event_free (event);
         break;
index 7f916ca..f4a0e67 100644 (file)
@@ -105,7 +105,8 @@ struct _GstFakeSrc {
   gboolean     silent;
   gboolean     dump;
   gboolean     need_flush;
-  gchar         *last_message;
+
+  gchar                *last_message;
 };
 
 struct _GstFakeSrcClass {
index 3f97331..c50e8c5 100644 (file)
@@ -78,7 +78,7 @@ GstElementDetails gst_filesrc_details = {
   "(C) 1999",
 };
 
-/*#define fs_print(format,args...) g_print(format, ## args)*/
+/*#define fs_print(format,args...) g_print(format, ## args) */
 #define fs_print(format,args...)
 
 /* FileSrc signals and args */
@@ -549,7 +549,7 @@ gst_filesrc_get (GstPad *pad)
 
   /* we're done, return the buffer */
   src->curoffset += GST_BUFFER_SIZE(buf);
-  g_object_notify (G_OBJECT (src), "offset");
+  //g_object_notify (G_OBJECT (src), "offset");
   return buf;
 }
 
@@ -590,7 +590,7 @@ gst_filesrc_open_file (GstFileSrc *src)
     /* now notify of the changes */
     g_object_freeze_notify (G_OBJECT (src));
     g_object_notify (G_OBJECT (src), "filesize");
-    g_object_notify (G_OBJECT (src), "offset");
+    //g_object_notify (G_OBJECT (src), "offset");
     g_object_thaw_notify (G_OBJECT (src));
 
     GST_FLAG_SET (src, GST_FILESRC_OPEN);
@@ -614,7 +614,7 @@ gst_filesrc_close_file (GstFileSrc *src)
   /* and notify that things changed */
   g_object_freeze_notify (G_OBJECT (src));
   g_object_notify (G_OBJECT (src), "filesize");
-  g_object_notify (G_OBJECT (src), "offset");
+  //g_object_notify (G_OBJECT (src), "offset");
   g_object_thaw_notify (G_OBJECT (src));
 
   if (src->mapbuf)
index ea38edc..2ea7428 100644 (file)
@@ -181,7 +181,7 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
   GList *pads;
 
   g_return_val_if_fail (GST_IS_TEE (element), NULL);
-
+  
   if (templ->direction != GST_PAD_SRC) {
     g_warning ("gsttee: request new pad that is not a SRC pad\n");
     return NULL;
index 620bafa..85d1c60 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -35,7 +35,6 @@
 #include <gst/gstpad.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstcpu.h>
-#include <gst/gstsystemclock.h>
 #include <gst/gstelement.h>
 #include <gst/gstbin.h>
 #include <gst/gstpipeline.h>
index cc3c3f6..7c50c6b 100644 (file)
@@ -152,78 +152,16 @@ gst_bin_new (const gchar * name)
   return gst_elementfactory_make ("bin", name);
 }
 
-static inline void
-gst_bin_reset_element_sched (GstElement * element, GstScheduler * sched)
-{
-  GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "resetting element's scheduler");
-
-  gst_element_set_sched (element, sched);
-}
-
-
-static void
-gst_bin_get_clock_elements (GstBin *bin, GList **needing, GList **providing) 
-{
-  GList *children = gst_bin_get_list (bin);
-
-  while (children) {
-    GstElement *child = GST_ELEMENT (children->data);
-
-    if (GST_IS_BIN (child)) {
-      gst_bin_get_clock_elements (GST_BIN (child), needing, providing);
-    }
-    if (child->getclockfunc) {
-      *providing = g_list_prepend (*providing, child);
-    }
-    if (child->setclockfunc) {
-      *needing = g_list_prepend (*needing, child);
-    }
-       
-    children = g_list_next (children);
-  }
-}
-
-static void
-gst_bin_distribute_clock (GstBin *bin, GList *needing, GstClock *clock)
-{
-  while (needing) {
-    GST_DEBUG (GST_CAT_CLOCK, "setting clock on %s", GST_ELEMENT_NAME (needing->data));
-    gst_element_set_clock (GST_ELEMENT (needing->data), clock);
-
-    needing = g_list_next (needing);
-  }
-}
-
-static void
-gst_bin_distribute_clocks (GstBin *bin)
-{
-  GList *needing = NULL, *providing = NULL;
-  GstClock *clock;
-      
-  gst_bin_get_clock_elements (bin, &needing, &providing);
-
-  if (GST_FLAG_IS_SET (bin, GST_BIN_FLAG_FIXED_CLOCK)) {
-    clock = bin->clock;
-  }
-  else if (providing) {
-    clock = gst_element_get_clock (GST_ELEMENT (providing->data));     
-  }
-  else {
-    GST_DEBUG (GST_CAT_CLOCK, "no clock provided, using default clock");
-    clock = gst_system_clock_obtain ();
-  }
-
-  GST_BIN_CLOCK (bin) = clock;
-  gst_bin_distribute_clock (bin, needing, clock);
-}
-
 GstClock*
 gst_bin_get_clock (GstBin *bin)
 {
   g_return_val_if_fail (bin != NULL, NULL);
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
-  return GST_BIN_CLOCK (bin);
+  if (GST_ELEMENT_SCHED (bin)) 
+    return gst_scheduler_get_clock (GST_ELEMENT_SCHED (bin));
+
+  return NULL;
 }
 
 void
@@ -232,8 +170,8 @@ gst_bin_use_clock (GstBin *bin, GstClock *clock)
   g_return_if_fail (bin != NULL);
   g_return_if_fail (GST_IS_BIN (bin));
 
-  GST_FLAG_SET (bin, GST_BIN_FLAG_FIXED_CLOCK);
-  GST_BIN_CLOCK (bin) = clock;
+  if (GST_ELEMENT_SCHED (bin)) 
+    gst_scheduler_use_clock (GST_ELEMENT_SCHED (bin), clock);
 }
 
 void
@@ -242,12 +180,12 @@ gst_bin_auto_clock (GstBin *bin)
   g_return_if_fail (bin != NULL);
   g_return_if_fail (GST_IS_BIN (bin));
 
-  GST_FLAG_UNSET (bin, GST_BIN_FLAG_FIXED_CLOCK);
-  GST_BIN_CLOCK (bin) = NULL;
+  if (GST_ELEMENT_SCHED (bin)) 
+    gst_scheduler_auto_clock (GST_ELEMENT_SCHED (bin));
 }
 
 static void
-gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
+gst_bin_set_element_sched (GstElement *element, GstScheduler *sched)
 {
   GList *children;
   GstElement *child;
@@ -264,6 +202,7 @@ gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
   if (GST_IS_BIN (element)) {
     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
       GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is already a manager, not resetting");
+      gst_scheduler_add_scheduler (sched, GST_ELEMENT_SCHED (element));
       return;
     }
 
@@ -278,7 +217,6 @@ gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
 
       gst_bin_set_element_sched (child, sched);
     }
-
   }
   /* otherwise, if it's just a regular old element */
   else {
@@ -288,7 +226,7 @@ gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
 
 
 static void
-gst_bin_unset_element_sched (GstElement * element)
+gst_bin_unset_element_sched (GstElement *element, GstScheduler *sched)
 {
   GList *children;
   GstElement *child;
@@ -302,7 +240,7 @@ gst_bin_unset_element_sched (GstElement * element)
     return;
   }
   
-  GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from it sched %p",
+  GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from its sched %p",
            GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element));
 
   /* if it's actually a Bin */
@@ -311,20 +249,21 @@ gst_bin_unset_element_sched (GstElement * element)
     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
       GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element,
                        "child is already a manager, not unsetting sched");
+      if (sched) {
+        gst_scheduler_remove_scheduler (sched, GST_ELEMENT_SCHED (element));
+      }
       return;
     }
-
-    gst_scheduler_remove_element (GST_ELEMENT_SCHED (element), element);
-
     /* for each child, remove them from their schedule */
     children = GST_BIN (element)->children;
     while (children) {
       child = GST_ELEMENT (children->data);
       children = g_list_next (children);
 
-      gst_bin_unset_element_sched (child);
+      gst_bin_unset_element_sched (child, sched);
     }
 
+    gst_scheduler_remove_element (GST_ELEMENT_SCHED (element), element);
   }
   /* otherwise, if it's just a regular old element */
   else {
@@ -372,10 +311,11 @@ gst_bin_add_many (GstBin *bin, GstElement *element_1, ...)
  * add a reference.
  */
 void
-gst_bin_add (GstBin * bin, GstElement * element)
+gst_bin_add (GstBin *bin, GstElement *element)
 {
   gint state_idx = 0;
   GstElementState state;
+  GstScheduler *sched;
 
   g_return_if_fail (bin != NULL);
   g_return_if_fail (GST_IS_BIN (bin));
@@ -409,11 +349,9 @@ gst_bin_add (GstBin * bin, GstElement * element)
   /* now we have to deal with manager stuff 
    * we can only do this if there's a scheduler: 
    * if we're not a manager, and aren't attached to anything, we have no sched (yet) */
-  if (GST_IS_BIN (element) && GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
-    GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is a manager");
-  }
-  else if (GST_ELEMENT_SCHED (bin) != NULL) {
-    gst_bin_set_element_sched (element, GST_ELEMENT_SCHED (bin));
+  sched = GST_ELEMENT_SCHED (bin);
+  if (sched) {
+    gst_bin_set_element_sched (element, sched);
   }
 
   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "added child \"%s\"", GST_ELEMENT_NAME (element));
@@ -429,7 +367,7 @@ gst_bin_add (GstBin * bin, GstElement * element)
  * Remove the element from its associated bin, unparenting as well.
  */
 void
-gst_bin_remove (GstBin * bin, GstElement * element)
+gst_bin_remove (GstBin *bin, GstElement *element)
 {
   gint state_idx = 0;
   GstElementState state;
@@ -456,7 +394,7 @@ gst_bin_remove (GstBin * bin, GstElement * element)
   }
 
   /* remove this element from the list of managed elements */
-  gst_bin_unset_element_sched (element);
+  gst_bin_unset_element_sched (element, GST_ELEMENT_SCHED (bin));
 
   /* now remove the element from the list of elements */
   bin->children = g_list_remove (bin->children, element);
@@ -504,7 +442,7 @@ gst_bin_child_state_change (GstBin *bin, GstElementState oldstate, GstElementSta
   GST_LOCK (bin);
   bin->child_states[old_idx]--;
   bin->child_states[new_idx]++;
-
+  
   for (i = GST_NUM_STATES - 1; i >= 0; i--) {
     if (bin->child_states[i] != 0) {
       gint state = (1 << i);
@@ -512,7 +450,9 @@ gst_bin_child_state_change (GstBin *bin, GstElementState oldstate, GstElementSta
        GST_INFO (GST_CAT_STATES, "bin %s need state change to %s",
                  GST_ELEMENT_NAME (bin), gst_element_statename (state));
        GST_STATE_PENDING (bin) = state;
+        GST_UNLOCK (bin);
        gst_bin_change_state_norecurse (bin);
+       return;
       }
       break;
     }
@@ -542,7 +482,11 @@ gst_bin_change_state (GstElement * element)
   GST_INFO_ELEMENT (GST_CAT_STATES, element, "changing childrens' state from %s to %s",
                    gst_element_statename (old_state), gst_element_statename (pending));
 
+  if (pending == GST_STATE_VOID_PENDING)
+    return GST_STATE_SUCCESS;
+
   children = bin->children;
+
   while (children) {
     child = GST_ELEMENT (children->data);
     children = g_list_next (children);
@@ -569,28 +513,6 @@ gst_bin_change_state (GstElement * element)
     }
   }
 
-  if (GST_ELEMENT_SCHED (bin) != NULL && GST_ELEMENT_PARENT (bin) == NULL) {
-    switch (transition) {
-      case GST_STATE_NULL_TO_READY:
-        gst_bin_distribute_clocks (bin);
-       break;
-      case GST_STATE_READY_TO_PAUSED:
-        if (GST_BIN_CLOCK (bin))
-          gst_clock_reset (GST_BIN_CLOCK (bin));
-        break;
-      case GST_STATE_PAUSED_TO_PLAYING:
-        gst_bin_distribute_clocks (bin);
-        if (GST_BIN_CLOCK (bin))
-          gst_clock_activate (GST_BIN_CLOCK (bin), TRUE);
-        break;
-      case GST_STATE_PLAYING_TO_PAUSED:
-        if (GST_BIN_CLOCK (bin))
-          gst_clock_activate (GST_BIN_CLOCK (bin), FALSE);
-        break;
-    }
-  }
-
-
   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),
index 016ddec..4e433ea 100644 (file)
@@ -48,10 +48,6 @@ extern GType _gst_bin_type;
 # define GST_BIN_CLASS               GST_BIN_CLASS_CAST
 #endif
 
-#define GST_BIN_CLOCK_PROVIDERS(bin)   (GST_BIN(bin)->clock_providers)
-#define GST_BIN_CLOCK_RECEIVERS(bin)   (GST_BIN(bin)->clock_receivers)
-#define GST_BIN_CLOCK(bin)             (GST_BIN(bin)->clock)
-
 typedef enum {
   /* this bin is a manager of child elements, i.e. a pipeline or thread */
   GST_BIN_FLAG_MANAGER         = GST_ELEMENT_FLAG_LAST,
@@ -82,8 +78,6 @@ struct _GstBin {
 
   GstElementState child_states[GST_NUM_STATES];
 
-  GstClock     *clock;
-  
   gpointer      sched_private;
 };
 
@@ -128,9 +122,6 @@ void                gst_bin_auto_clock              (GstBin *bin);
 /* one of our childs signaled a state change */
 void           gst_bin_child_state_change      (GstBin *bin, GstElementState oldstate, 
                                                 GstElementState newstate, GstElement *child);
-/* one of our childs signaled an error */
-void           gst_bin_child_error             (GstBin *bin, GstElement *child);
-
 
 #ifdef __cplusplus
 }
index 83f1065..cb2707e 100644 (file)
 #include "gstcaps.h"
 #include "gsttype.h"
 
-#include "gstpropsprivate.h"
-
 static GMemChunk *_gst_caps_chunk;
 static GMutex *_gst_caps_chunk_lock;
 
+GType _gst_caps_type;
+
 void
 _gst_caps_initialize (void)
 {
@@ -38,6 +38,11 @@ _gst_caps_initialize (void)
                   sizeof (GstCaps), sizeof (GstCaps) * 256,
                   G_ALLOC_AND_FREE);
   _gst_caps_chunk_lock = g_mutex_new ();
+
+  _gst_caps_type = g_boxed_type_register_static ("GstCaps",
+                                       (GBoxedCopyFunc) gst_caps_ref,
+                                       (GBoxedFreeFunc) gst_caps_unref);
+
 }
 
 static guint16
@@ -104,7 +109,6 @@ gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props)
   caps->properties = props;
   caps->next = NULL;
   caps->refcount = 1;
-  caps->lock = g_mutex_new ();
   if (props)
     caps->fixed = props->fixed;
   else
@@ -128,11 +132,8 @@ gst_caps_destroy (GstCaps *caps)
   if (caps == NULL)
     return;
   
-  GST_CAPS_LOCK (caps);
   next = caps->next;
-  GST_CAPS_UNLOCK (caps);
 
-  g_mutex_free (caps->lock);
   gst_props_unref (caps->properties);
   g_free (caps->name);
   g_mutex_lock (_gst_caps_chunk_lock);
@@ -189,11 +190,9 @@ gst_caps_unref (GstCaps *caps)
 
   g_return_val_if_fail (caps->refcount > 0, NULL);
 
-  GST_CAPS_LOCK (caps);
   caps->refcount--;
   zero = (caps->refcount == 0);
   next = &caps->next;
-  GST_CAPS_UNLOCK (caps);
 
   if (*next)
     *next = gst_caps_unref (*next);
@@ -218,9 +217,7 @@ gst_caps_ref (GstCaps *caps)
 {
   g_return_val_if_fail (caps != NULL, NULL);
 
-  GST_CAPS_LOCK (caps);
   caps->refcount++;
-  GST_CAPS_UNLOCK (caps);
 
   return caps;
 }
@@ -296,9 +293,7 @@ gst_caps_copy_on_write (GstCaps *caps)
 
   g_return_val_if_fail (caps != NULL, NULL);
 
-  GST_CAPS_LOCK (caps);
   needcopy = (caps->refcount > 1);
-  GST_CAPS_UNLOCK (caps);
 
   if (needcopy) {
     new = gst_caps_copy (caps);
@@ -798,7 +793,6 @@ gst_caps_load_thyself (xmlNodePtr parent)
       g_mutex_unlock (_gst_caps_chunk_lock);
 
       caps->refcount = 1;
-      caps->lock = g_mutex_new ();
       caps->next = NULL;
       caps->fixed = TRUE;
        
index 39ee56d..01d5d6a 100644 (file)
 
 typedef struct _GstCaps GstCaps;
 
+extern GType _gst_caps_type;
+
+#define GST_TYPE_CAPS  (_get_caps_type)
+
+
 #define GST_CAPS(caps) \
   ((GstCaps *)(caps))
 
-#define GST_CAPS_LOCK(caps)    (g_mutex_lock(GST_CAPS(caps)->lock))
-#define GST_CAPS_TRYLOCK(caps) (g_mutex_trylock(GST_CAPS(caps)->lock))
-#define GST_CAPS_UNLOCK(caps)  (g_mutex_unlock(GST_CAPS(caps)->lock))
-
 #define GST_CAPS_IS_FIXED(caps)                ((caps)->fixed)
 #define GST_CAPS_IS_CHAINED(caps)      ((caps)->next)
 
@@ -45,7 +46,6 @@ struct _GstCaps {
   guint16      id;                     /* type id (major type) */
 
   guint        refcount;               
-  GMutex       *lock;                  /* global lock for this capability */
   gboolean     fixed;                  /* this caps doesn't contain variable properties */
 
   GstProps     *properties;            /* properties for this capability */
@@ -104,14 +104,16 @@ GstCaps*  gst_caps_set_props                      (GstCaps *caps, GstProps *props);
 GstProps*      gst_caps_get_props                      (GstCaps *caps);
 
 #define                gst_caps_set(caps, name, args...)       gst_props_set ((caps)->properties, name, args)
+#define                gst_caps_get(caps, name, args...)       gst_props_get ((caps)->properties, name, args)
 
-#define                gst_caps_get_int(caps, name)            gst_props_get_int ((caps)->properties, name)
-#define                gst_caps_get_float(caps, name)          gst_props_get_float ((caps)->properties, name)
-#define                gst_caps_get_fourcc_int(caps, name)     gst_props_get_fourcc_int ((caps)->properties, name)
-#define                gst_caps_get_boolean(caps, name)        gst_props_get_boolean ((caps)->properties, name)
-#define                gst_caps_get_string(caps, name)         gst_props_get_string ((caps)->properties, name)
+#define                gst_caps_get_int(caps,name,res)         gst_props_entry_get_int(gst_props_get_entry((caps)->properties,name),res)
+#define                gst_caps_get_float(caps,name,res)       gst_props_entry_get_float(gst_props_get_entry((caps)->properties,name),res)
+#define                gst_caps_get_fourcc_int(caps,name,res)  gst_props_entry_get_fourcc_int(gst_props_get_entry((caps)->properties,name),res)
+#define                gst_caps_get_boolean(caps,name,res)     gst_props_entry_get_boolean(gst_props_get_entry((caps)->properties,name),res)
+#define                gst_caps_get_string(caps,name,res)      gst_props_entry_get_string(gst_props_get_entry((caps)->properties,name),res)
 
 #define                gst_caps_has_property(caps, name)       gst_props_has_property ((caps)->properties, name)
+#define                gst_caps_has_property_typed(caps, name) gst_props_has_property_typed ((caps)->properties, name)
 #define                gst_caps_has_fixed_property(caps, name) gst_props_has_fixed_property ((caps)->properties, name)
 
 GstCaps*       gst_caps_get_by_name                    (GstCaps *caps, const gchar *name);
index fb1c2ff..e96c717 100644 (file)
 
 #define CLASS(clock)  GST_CLOCK_CLASS (G_OBJECT_GET_CLASS (clock))
 
+static GMemChunk *_gst_clock_entries_chunk;
+static GMutex *_gst_clock_entries_chunk_lock;
+static GList *_gst_clock_entries_pool;
 
 static void            gst_clock_class_init            (GstClockClass *klass);
 static void            gst_clock_init                  (GstClock *clock);
 
+
 static GstObjectClass *parent_class = NULL;
 /* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
 
+typedef struct _GstClockEntry GstClockEntry;
+
+static void            gst_clock_free_entry            (GstClock *clock, GstClockEntry *entry);
+
+typedef enum {
+  GST_ENTRY_OK,
+  GST_ENTRY_RESTART,
+} GstEntryStatus;
+
+struct _GstClockEntry {
+  GstClockTime                  time;
+  GstEntryStatus        status;
+  GstClockCallback      func;
+  gpointer              user_data;
+  GMutex               *lock;
+  GCond                *cond;
+};
+
+#define GST_CLOCK_ENTRY(entry)          ((GstClockEntry *)(entry))
+#define GST_CLOCK_ENTRY_TIME(entry)     (((GstClockEntry *)(entry))->time)
+#define GST_CLOCK_ENTRY_LOCK(entry)     (g_mutex_lock ((entry)->lock))
+#define GST_CLOCK_ENTRY_UNLOCK(entry)   (g_mutex_unlock ((entry)->lock))
+#define GST_CLOCK_ENTRY_SIGNAL(entry)   (g_cond_signal ((entry)->cond))
+#define GST_CLOCK_ENTRY_WAIT(entry)     (g_cond_wait (entry->cond, entry->lock))
+#define GST_CLOCK_ENTRY_TIMED_WAIT(entry, time)         (g_cond_timed_wait (entry->cond, entry->lock, (time)))
+
+static GstClockEntry*
+gst_clock_entry_new (GstClockTime time,
+                    GstClockCallback func, gpointer user_data)
+{
+  GstClockEntry *entry;
+
+  g_mutex_lock (_gst_clock_entries_chunk_lock);
+  if (_gst_clock_entries_pool) {
+    entry = GST_CLOCK_ENTRY (_gst_clock_entries_pool->data);
+
+    _gst_clock_entries_pool = g_list_remove (_gst_clock_entries_pool, entry);
+    g_mutex_unlock (_gst_clock_entries_chunk_lock);
+  }
+  else {
+    entry = g_mem_chunk_alloc (_gst_clock_entries_chunk);
+    g_mutex_unlock (_gst_clock_entries_chunk_lock);
+
+    entry->lock = g_mutex_new ();
+    entry->cond = g_cond_new ();
+  }
+  entry->time = time;
+  entry->func = func;
+  entry->user_data = user_data;
+
+  return entry;
+}
+
+static gint
+clock_compare_func (gconstpointer a,
+                    gconstpointer b)
+{
+  GstClockEntry *entry1 = (GstClockEntry *)a;
+  GstClockEntry *entry2 = (GstClockEntry *)b;
+
+  return (entry1->time - entry2->time);
+}
+
 GType
 gst_clock_get_type (void)
 {
@@ -43,19 +110,19 @@ gst_clock_get_type (void)
 
   if (!clock_type) {
     static const GTypeInfo clock_info = {
-      sizeof (GstObjectClass),
+      sizeof (GstClockClass),
       NULL,
       NULL,
       (GClassInitFunc) gst_clock_class_init,
       NULL,
       NULL,
-      sizeof (GstObject),
+      sizeof (GstClock),
       4,
       (GInstanceInitFunc) gst_clock_init,
       NULL
     };
     clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock", 
-                                        &clock_info, G_TYPE_FLAG_ABSTRACT);
+                                        &clock_info,  G_TYPE_FLAG_ABSTRACT);
   }
   return clock_type;
 }
@@ -70,6 +137,12 @@ gst_clock_class_init (GstClockClass *klass)
   gstobject_class = (GstObjectClass*) klass;
 
   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+
+  _gst_clock_entries_chunk = g_mem_chunk_new ("GstClockEntries",
+                     sizeof (GstClockEntry), sizeof (GstClockEntry) * 32,
+                     G_ALLOC_AND_FREE);
+  _gst_clock_entries_chunk_lock = g_mutex_new ();
+  _gst_clock_entries_pool = NULL;
 }
 
 static void
@@ -78,37 +151,66 @@ gst_clock_init (GstClock *clock)
   clock->speed = 1.0;
   clock->active = FALSE;
   clock->start_time = 0;
+  clock->last_time = 0;
+  clock->entries = NULL;
+  clock->async_supported = FALSE;
 
   clock->active_mutex = g_mutex_new ();
   clock->active_cond = g_cond_new ();
 }
 
+gboolean
+gst_clock_async_supported (GstClock *clock)
+{
+  g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
+
+  return clock->async_supported;
+}
+
+
 void
 gst_clock_reset (GstClock *clock)
 {
+  GstClockTime time = 0LL;
+
   g_return_if_fail (GST_IS_CLOCK (clock));
 
-  clock->start_time = 0;
-  clock->active = FALSE;
+  if (CLASS (clock)->get_internal_time) {
+    time = CLASS (clock)->get_internal_time (clock);
+  }
 
-  if (CLASS (clock)->reset)
-    CLASS (clock)->reset (clock);
+  GST_LOCK (clock);
+  clock->active = FALSE;
+  clock->start_time = time;
+  clock->last_time = 0LL;
+  GST_UNLOCK (clock);
 }
 
 void
 gst_clock_activate (GstClock *clock, gboolean active)
 {
+  GstClockTime time = 0LL;
+
   g_return_if_fail (GST_IS_CLOCK (clock));
 
   clock->active = active;
+               
+  if (CLASS (clock)->get_internal_time) {
+    time = CLASS (clock)->get_internal_time (clock);
+  }
 
-  if (CLASS (clock)->activate)
-    CLASS (clock)->activate (clock, active);
+  GST_LOCK (clock);
+  if (active) {
+    clock->start_time = time - clock->last_time;;
+  }
+  else {
+    clock->last_time = time - clock->start_time;
+  }
+  GST_UNLOCK (clock);
 
   g_mutex_lock (clock->active_mutex);  
-  g_cond_signal (clock->active_cond);  
+  g_cond_broadcast (clock->active_cond);       
   g_mutex_unlock (clock->active_mutex);        
-
 }
 
 gboolean
@@ -119,40 +221,166 @@ gst_clock_is_active (GstClock *clock)
   return clock->active;
 }
 
-void
-gst_clock_set_time (GstClock *clock, GstClockTime time)
-{
-  g_return_if_fail (GST_IS_CLOCK (clock));
-
-  if (CLASS (clock)->set_time)
-    CLASS (clock)->set_time (clock, time);
-}
-
 GstClockTime
 gst_clock_get_time (GstClock *clock)
 {
+  GstClockTime ret = 0LL;
+
   g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
 
-  if (CLASS (clock)->get_time)
-    return CLASS (clock)->get_time (clock);
+  if (!clock->active) {
+    /* clock is not activen return previous time */
+    ret = clock->last_time;
+  }
+  else {
+    if (CLASS (clock)->get_internal_time) {
+      ret = CLASS (clock)->get_internal_time (clock) - clock->start_time;
+    }
+    /* make sure the time is increasing, else return last_time */
+    if (ret < clock->last_time) {
+      ret = clock->last_time;
+    }
+    else {
+      clock->last_time = ret;
+    }
+  }
 
-  return 0LL;
+  return ret;
 }
 
-GstClockReturn
-gst_clock_wait (GstClock *clock, GstClockTime time)
+static GstClockID
+gst_clock_wait_async_func (GstClock *clock, GstClockTime time,
+                          GstClockCallback func, gpointer user_data)
 {
-  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
+  GstClockEntry *entry = NULL;
+  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
 
   if (!clock->active) {
     g_mutex_lock (clock->active_mutex);        
     g_cond_wait (clock->active_cond, clock->active_mutex);     
     g_mutex_unlock (clock->active_mutex);      
   }
-  if (CLASS (clock)->wait)
-    return CLASS (clock)->wait (clock, time);
 
-  return GST_CLOCK_TIMEOUT;
+  entry = gst_clock_entry_new (time, func, user_data);
+
+  GST_LOCK (clock);
+  clock->entries = g_list_insert_sorted (clock->entries, entry, clock_compare_func);
+  GST_UNLOCK (clock);
+
+  return entry;
+}
+
+GstClockReturn
+gst_clock_wait (GstClock *clock, GstClockTime time)
+{
+  GstClockID id;
+  GstClockReturn res;
+  
+  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
+
+  id = gst_clock_wait_async_func (clock, time, NULL, NULL);
+  res = gst_clock_wait_id (clock, id);
+
+  return res;
+}
+
+GstClockID
+gst_clock_wait_async (GstClock *clock, GstClockTime time,
+                     GstClockCallback func, gpointer user_data)
+{
+  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
+
+  if (clock->async_supported) {
+    return gst_clock_wait_async_func (clock, time, func, user_data);
+  }
+  return NULL;
+}
+
+static void
+gst_clock_unlock_func (GstClock *clock, GstClockTime time, GstClockID id, gpointer user_data)
+{
+  GstClockEntry *entry = (GstClockEntry *) id;
+
+  GST_CLOCK_ENTRY_LOCK (entry);
+  GST_CLOCK_ENTRY_SIGNAL (entry);
+  GST_CLOCK_ENTRY_UNLOCK (entry);
+}
+
+GstClockReturn
+gst_clock_wait_id (GstClock *clock, GstClockID id)
+{
+  GstClockReturn res = GST_CLOCK_TIMEOUT;
+  GstClockEntry *entry = (GstClockEntry *) id;
+  GstClockTime current_real, current, target;
+  GTimeVal timeval;
+  
+  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_ERROR);
+  g_return_val_if_fail (entry, GST_CLOCK_ERROR);
+
+  current = gst_clock_get_time (clock);
+
+  g_get_current_time (&timeval);
+  current_real = GST_TIMEVAL_TO_TIME (timeval);
+
+  GST_CLOCK_ENTRY_LOCK (entry);
+  entry->func = gst_clock_unlock_func;
+  target = GST_CLOCK_ENTRY_TIME (entry) - current + current_real;
+
+  //g_print ("%lld %lld %lld\n", target, current, current_real);
+  
+  if (target > current_real) {
+    timeval.tv_usec = target % 1000000;
+    timeval.tv_sec = target / 1000000;
+
+    GST_CLOCK_ENTRY_TIMED_WAIT (entry, &timeval);
+  }
+  GST_CLOCK_ENTRY_UNLOCK (entry);
+
+  gst_clock_free_entry (clock, entry);
+
+  return res;
+}
+
+GstClockID
+gst_clock_get_next_id (GstClock *clock)
+{
+  GstClockEntry *entry = NULL;
+
+  GST_LOCK (clock);
+  if (clock->entries)
+    entry = GST_CLOCK_ENTRY (clock->entries->data);
+  GST_UNLOCK (clock);
+
+  return (GstClockID *) entry;
+}
+
+GstClockTime
+gst_clock_id_get_time (GstClockID id)
+{
+  return GST_CLOCK_ENTRY_TIME (id);
+}
+
+static void
+gst_clock_free_entry (GstClock *clock, GstClockEntry *entry)
+{
+  GST_LOCK (clock);
+  clock->entries = g_list_remove (clock->entries, entry);
+  GST_UNLOCK (clock);
+
+  g_mutex_lock (_gst_clock_entries_chunk_lock);
+  _gst_clock_entries_pool = g_list_prepend (_gst_clock_entries_pool, entry);
+  g_mutex_unlock (_gst_clock_entries_chunk_lock);
+}
+
+void
+gst_clock_unlock_id (GstClock *clock, GstClockID id)
+{
+  GstClockEntry *entry = (GstClockEntry *) id;
+
+  if (entry->func)
+    entry->func (clock, gst_clock_get_time (clock), id, entry->user_data);
+
+  gst_clock_free_entry (clock, entry);
 }
 
 void
@@ -172,6 +400,6 @@ gst_clock_get_resolution (GstClock *clock)
   if (CLASS (clock)->get_resolution)
     return CLASS (clock)->get_resolution (clock);
 
-  return 0LL;
+  return 1LL;
 }
 
index 08bdd13..027bdec 100644 (file)
@@ -65,8 +65,11 @@ struct _GstClock {
   GstObject     object;
 
   GstClockTime  start_time;
+  GstClockTime  last_time;
   gdouble       speed;
   gboolean      active;
+  GList                *entries;
+  gboolean      async_supported;
 
   GMutex       *active_mutex;
   GCond                *active_cond;
@@ -76,20 +79,8 @@ struct _GstClockClass {
   GstObjectClass        parent_class;
 
   /* vtable */
-  void                         (*activate)             (GstClock *clock, gboolean active);
-  void                         (*reset)                (GstClock *clock);
-
-  void                         (*set_time)             (GstClock *clock, GstClockTime time);
-  GstClockTime                 (*get_time)             (GstClock *clock);
-
-  GstClockReturn       (*wait)                 (GstClock *clock, GstClockTime time);
-  GstClockID           (*wait_async)           (GstClock *clock, GstClockTime time, 
-                                                GstClockCallback func, gpointer user_data);
-  void                         (*cancel_wait_async)    (GstClock *clock, GstClockID id);
-  GstClockID           (*notify_async)         (GstClock *clock, GstClockTime interval, 
-                                                GstClockCallback func, gpointer user_data);
-  void                         (*remove_notify_async)  (GstClock *clock, GstClockID id);
-       
+  GstClockTime                 (*get_internal_time)    (GstClock *clock);
+
   void                         (*set_resolution)       (GstClock *clock, guint64 resolution);
   guint64              (*get_resolution)       (GstClock *clock);
 
@@ -104,8 +95,8 @@ void                         gst_clock_get_speed             (GstClock *clock, gdouble speed);
 void                   gst_clock_activate              (GstClock *clock, gboolean active);
 gboolean               gst_clock_is_active             (GstClock *clock);
 void                   gst_clock_reset                 (GstClock *clock);
+gboolean               gst_clock_async_supported       (GstClock *clock);
 
-void                   gst_clock_set_time              (GstClock *clock, GstClockTime time);
 GstClockTime           gst_clock_get_time              (GstClock *clock);
 
 GstClockReturn         gst_clock_wait                  (GstClock *clock, GstClockTime time);
@@ -115,6 +106,12 @@ void                       gst_clock_cancel_wait_async     (GstClock *clock, GstClockID id);
 GstClockID             gst_clock_notify_async          (GstClock *clock, GstClockTime interval, 
                                                         GstClockCallback func, gpointer user_data);
 void                   gst_clock_remove_notify_async   (GstClock *clock, GstClockID id);
+GstClockReturn         gst_clock_wait_id               (GstClock *clock, GstClockID id);
+
+GstClockID             gst_clock_get_next_id           (GstClock *clock);
+void                   gst_clock_unlock_id             (GstClock *clock, GstClockID id);
+
+GstClockTime           gst_clock_id_get_time           (GstClockID id);
 
 void                   gst_clock_set_resolution        (GstClock *clock, guint64 resolution);
 guint64                        gst_clock_get_resolution        (GstClock *clock);
index 0147a07..1116af1 100644 (file)
@@ -315,8 +315,11 @@ gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
   g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
 
-  /* FIXME inform the scheduler */
-  return gst_clock_wait (clock, time);
+  if (GST_ELEMENT_SCHED (element)) {
+    return gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time);
+  }
+  else 
+    return GST_CLOCK_TIMEOUT;
 }
 
 /**
@@ -489,7 +492,9 @@ gst_element_get_pad (GstElement *element, const gchar *name)
   /* look through the list, matching by name */
   walk = element->pads;
   while (walk) {
-    GstPad *pad = GST_PAD(walk->data);
+    GstPad *pad;
+    
+    pad = GST_PAD(walk->data);
     if (!strcmp (GST_PAD_NAME(pad), name)) {
       GST_INFO(GST_CAT_ELEMENT_PADS,"found pad %s:%s",GST_DEBUG_PAD_NAME(pad));
       return pad;
@@ -718,6 +723,7 @@ gst_element_request_pad_by_name (GstElement *element, const gchar *name)
   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
+
   if (strstr (name, "%")) {
     templ = gst_element_get_padtemplate_by_name (element, name);
     req_name = NULL;
@@ -1182,35 +1188,6 @@ gst_element_error (GstElement *element, const gchar *error, ...)
 }
 
 /**
- * gst_element_info:
- * @element: Element with the info
- * @info: String describing the info
- * @...: arguments for the string.
- *
- * 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, ...)
-{
-  g_warning ("The function gst_element_info is gone. Use g_object_notify instead.");
-}
-
-
-/**
- * gst_element_send_event:
- * @element: Element generating the event
- * @event: the event to send
- *
- * This function is deprecated and doesn't work anymore.
- */
-void
-gst_element_send_event (GstElement *element, GstEvent *event)
-{
-  g_warning ("The function gst_element_send_event is gone. Use g_object_notify instead.");
-}
-
-/**
  * gst_element_get_state:
  * @element: element to get state of
  *
@@ -1258,13 +1235,13 @@ gst_element_set_state (GstElement *element, GstElementState state)
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
 
-  GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s\n",
-                     gst_element_statename (GST_STATE (element)),
-                     gst_element_statename (state));
-
   /* start with the current state */
   curpending = GST_STATE(element);
 
+  GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s\n",
+                     gst_element_statename (curpending),
+                     gst_element_statename (state));
+
   /* loop until the final requested state is set */
   while (GST_STATE (element) != state && GST_STATE (element) != GST_STATE_VOID_PENDING) {
     /* move the curpending state in the correct direction */
@@ -1277,9 +1254,10 @@ gst_element_set_state (GstElement *element, GstElementState state)
     /* FIXME: should probably check to see that we don't already have one */
     GST_STATE_PENDING (element) = curpending;
 
-    if (curpending != state)
+    if (curpending != state) {
       GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "intermediate: setting state to %s\n",
                          gst_element_statename (curpending));
+    }
 
     /* call the state change function so it can set the state */
     oclass = CLASS (element);
@@ -1297,7 +1275,11 @@ gst_element_set_state (GstElement *element, GstElementState state)
         /* Last thing we do is verify that a successful state change really
          * did change the state... */
         if (GST_STATE (element) != curpending) {
-          GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element claimed state-change success, but state didn't change\n");
+          GST_DEBUG_ELEMENT (GST_CAT_STATES, element, 
+                         "element claimed state-change success, but state didn't change %s, %s <-> %s\n",
+                         gst_element_statename (GST_STATE (element)),
+                         gst_element_statename (GST_STATE_PENDING (element)),
+                         gst_element_statename (curpending));
           return GST_STATE_FAILURE;
        }
         break;
@@ -1429,9 +1411,6 @@ gst_element_change_state (GstElement *element)
     }
   }
 
-  g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
-                 0, old_state, GST_STATE (element));
-
   parent = GST_ELEMENT_PARENT (element);
 
   /* tell our parent about the state change */
@@ -1439,6 +1418,9 @@ gst_element_change_state (GstElement *element)
     gst_bin_child_state_change (GST_BIN (parent), old_state, GST_STATE (element), element);
   }
 
+  g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
+                 0, old_state, GST_STATE (element));
+
   /* signal the state change in case somebody is waiting for us */
   g_mutex_lock (element->state_mutex);
   g_cond_signal (element->state_cond);
@@ -1688,7 +1670,7 @@ gst_element_interrupt (GstElement *element)
  */
 void
 gst_element_set_sched (GstElement *element,
-                        GstScheduler *sched)
+                      GstScheduler *sched)
 {
   g_return_if_fail (GST_IS_ELEMENT (element));
   
@@ -1727,8 +1709,8 @@ gst_element_get_sched (GstElement *element)
  * a new loopfunc to be assigned, this should be no problem.
  */
 void
-gst_element_set_loop_function(GstElement *element,
-                              GstElementLoopFunction loop)
+gst_element_set_loop_function (GstElement *element,
+                               GstElementLoopFunction loop)
 {
   g_return_if_fail (GST_IS_ELEMENT (element));
 
index 7440cba..affb351 100644 (file)
@@ -38,7 +38,6 @@ extern "C" {
 
 #define GST_NUM_STATES 4
 
-
 /* NOTE: this probably should be done with an #ifdef to decide 
  * whether to safe-cast or to just do the non-checking cast.
  */
@@ -171,7 +170,6 @@ struct _GstElementClass {
   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);
@@ -228,8 +226,7 @@ gboolean            gst_element_connect_elements_many (GstElement *element_1, GstElement *
 
 void                   gst_element_set_eos             (GstElement *element);
 
-void                   gst_element_send_event          (GstElement *element, GstEvent *event);
-
+void                   gst_element_error               (GstElement *element, const gchar *error, ...);
 
 GstElementState         gst_element_get_state           (GstElement *element);
 gint                   gst_element_set_state           (GstElement *element, GstElementState state);
@@ -238,9 +235,6 @@ void                        gst_element_wait_state_change   (GstElement *element);
        
 const gchar*           gst_element_statename           (GstElementState state);
 
-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);
 
 void                    gst_element_class_install_std_props    (GstElementClass *klass,
index b6908d9..7b00de0 100644 (file)
@@ -535,7 +535,7 @@ gst_pad_disconnect (GstPad *srcpad,
   realsink = GST_PAD_REALIZE (sinkpad);
 
   g_return_if_fail (GST_RPAD_PEER (realsrc) != NULL);
-  g_return_if_fail (GST_RPAD_PEER (realsink) != NULL);
+  g_return_if_fail (GST_RPAD_PEER (realsink) == realsrc);
 
   if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
       (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
@@ -1013,8 +1013,8 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
        debug_string = "DELAYED";
        break;
       default:
-       g_warning ("unknown return code from connect function of pad %s:%s",
-            GST_DEBUG_PAD_NAME (pad));
+       g_warning ("unknown return code from connect function of pad %s:%s %d",
+            GST_DEBUG_PAD_NAME (pad), res);
         return GST_PAD_CONNECT_REFUSED;
     }
 
@@ -1337,9 +1337,9 @@ gst_pad_proxy_connect (GstPad *pad, GstCaps *caps)
   GST_INFO (GST_CAT_CAPS, "proxy connect to pad %s:%s",
             GST_DEBUG_PAD_NAME (realpad));
 
-  if (peer && !gst_pad_try_set_caps_func (peer, caps, TRUE))
+  if (peer && gst_pad_try_set_caps_func (peer, caps, TRUE) < 0)
     return GST_PAD_CONNECT_REFUSED;
-  if (!gst_pad_try_set_caps_func (realpad, caps, FALSE))
+  if (gst_pad_try_set_caps_func (realpad, caps, FALSE) < 0)
     return GST_PAD_CONNECT_REFUSED;
 
   return GST_PAD_CONNECT_OK;
index b136f9e..f46418d 100644 (file)
@@ -40,7 +40,7 @@ extern GType _gst_pad_type;
 extern GType _gst_real_pad_type;
 extern GType _gst_ghost_pad_type;
 
-/*#define GST_TYPE_PARANOID */
+#define GST_TYPE_PARANOID 
 
 /* 
  * Pad base class
@@ -118,10 +118,10 @@ typedef enum {
 } GstRegionType;
 
 typedef enum {
-  GST_PAD_CONNECT_REFUSED = 0,
-  GST_PAD_CONNECT_OK      = 1,
-  GST_PAD_CONNECT_DONE    = 2,
-  GST_PAD_CONNECT_DELAYED = 3,
+  GST_PAD_CONNECT_REFUSED = -1,
+  GST_PAD_CONNECT_DELAYED =  0,
+  GST_PAD_CONNECT_OK      =  1,
+  GST_PAD_CONNECT_DONE    =  2,
 } GstPadConnectReturn;
 
 /* this defines the functions used to chain buffers
index 2650731..f50c5be 100644 (file)
 
 #include "gstlog.h"
 #include "gstprops.h"
-#include "gstpropsprivate.h"
+
+GType _gst_props_type;
+
+#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_TYPE)
+
+struct _GstPropsEntry {
+  GQuark       propid;
+  GstPropsType         propstype;              
+
+  union {
+    /* flat values */
+    gboolean bool_data;
+    guint32  fourcc_data;
+    gint     int_data;
+    gfloat   float_data;
+
+    /* structured values */
+    struct {
+      GList *entries;
+    } list_data;
+    struct {
+      gchar *string;
+    } string_data;
+    struct {
+      gint min;
+      gint max;
+    } int_range_data;
+    struct {
+      gfloat min;
+      gfloat max;
+    } float_range_data;
+  } data;
+};
 
 static GMemChunk *_gst_props_entries_chunk;
 static GMutex *_gst_props_entries_chunk_lock;
@@ -49,6 +81,11 @@ _gst_props_initialize (void)
                  sizeof (GstProps), sizeof (GstProps) * 256, 
                  G_ALLOC_AND_FREE);
   _gst_props_chunk_lock = g_mutex_new ();
+
+  _gst_props_type = g_boxed_type_register_static ("GstProps",
+                                      (GBoxedCopyFunc) gst_props_ref,
+                                      (GBoxedFreeFunc) gst_props_unref);
+
 }
 
 static void
@@ -57,31 +94,31 @@ gst_props_debug_entry (GstPropsEntry *entry)
   const gchar *name = g_quark_to_string (entry->propid);
 
   switch (entry->propstype) {
-    case GST_PROPS_INT_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d", name, entry->data.int_data);
+    case GST_PROPS_INT_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d\n", name, entry->data.int_data);
       break;
-    case GST_PROPS_FLOAT_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f", name, entry->data.float_data);
+    case GST_PROPS_FLOAT_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f\n", name, entry->data.float_data);
       break;
-    case GST_PROPS_FOURCC_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %4.4s", name, (gchar*)&entry->data.fourcc_data);
+    case GST_PROPS_FOURCC_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %4.4s\n", name, (gchar*)&entry->data.fourcc_data);
       break;
-    case GST_PROPS_BOOL_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d", name, entry->data.bool_data);
+    case GST_PROPS_BOOL_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d\n", name, entry->data.bool_data);
       break;
-    case GST_PROPS_STRING_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: string %s", name, entry->data.string_data.string);
+    case GST_PROPS_STRING_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: string %s\n", name, entry->data.string_data.string);
       break;
-    case GST_PROPS_INT_RANGE_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d", name, entry->data.int_range_data.min,
+    case GST_PROPS_INT_RANGE_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d\n", name, entry->data.int_range_data.min,
                      entry->data.int_range_data.max);
       break;
-    case GST_PROPS_FLOAT_RANGE_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f", name, entry->data.float_range_data.min,
+    case GST_PROPS_FLOAT_RANGE_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f\n", name, entry->data.float_range_data.min,
                      entry->data.float_range_data.max);
       break;
-    case GST_PROPS_LIST_ID:
-      GST_DEBUG (GST_CAT_PROPERTIES, "[list]");
+    case GST_PROPS_LIST_TYPE:
+      GST_DEBUG (GST_CAT_PROPERTIES, "[list]\n");
       {
        GList *entries = entry->data.list_data.entries;
 
@@ -122,30 +159,30 @@ props_find_func (gconstpointer a,
  */
 #define GST_PROPS_ENTRY_FILL(entry, var_args)                                  \
 G_STMT_START {                                                                         \
-  entry->propstype = va_arg (var_args, GstPropsId);                            \
+  entry->propstype = va_arg (var_args, GstPropsType);                          \
                                                                                \
   switch (entry->propstype) {                                                  \
-    case GST_PROPS_INT_ID:                                                     \
+    case GST_PROPS_INT_TYPE:                                                   \
       entry->data.int_data = va_arg (var_args, gint);                          \
       break;                                                                   \
-    case GST_PROPS_INT_RANGE_ID:                                               \
+    case GST_PROPS_INT_RANGE_TYPE:                                             \
       entry->data.int_range_data.min = va_arg (var_args, gint);                        \
       entry->data.int_range_data.max = va_arg (var_args, gint);                        \
       break;                                                                   \
-    case GST_PROPS_FLOAT_ID:                                                   \
+    case GST_PROPS_FLOAT_TYPE:                                                 \
       entry->data.float_data = va_arg (var_args, gdouble);                     \
       break;                                                                   \
-    case GST_PROPS_FLOAT_RANGE_ID:                                             \
+    case GST_PROPS_FLOAT_RANGE_TYPE:                                           \
       entry->data.float_range_data.min = va_arg (var_args, gdouble);           \
       entry->data.float_range_data.max = va_arg (var_args, gdouble);           \
       break;                                                                   \
-    case GST_PROPS_FOURCC_ID:                                                  \
+    case GST_PROPS_FOURCC_TYPE:                                                        \
       entry->data.fourcc_data = va_arg (var_args, gulong);                     \
       break;                                                                   \
-    case GST_PROPS_BOOL_ID:                                                    \
+    case GST_PROPS_BOOL_TYPE:                                                  \
       entry->data.bool_data = va_arg (var_args, gboolean);                     \
       break;                                                                   \
-    case GST_PROPS_STRING_ID:                                                  \
+    case GST_PROPS_STRING_TYPE:                                                        \
       entry->data.string_data.string = g_strdup (va_arg (var_args, gchar*));   \
       break;                                                                   \
     default:                                                                   \
@@ -153,6 +190,52 @@ G_STMT_START {                                                                     \
   }                                                                            \
 } G_STMT_END
 
+
+#define GST_PROPS_ENTRY_READ(entry, var_args, safe, result)                    \
+G_STMT_START {                                                                         \
+  *result = TRUE;                                                              \
+                                                                               \
+  if (safe) {                                                                  \
+    GstPropsType propstype = va_arg (var_args, GstPropsType);                  \
+    if (propstype != entry->propstype) {                                       \
+      *result = FALSE;                                                         \
+    }                                                                          \
+  }                                                                            \
+  if (*result) {                                                               \
+    switch (entry->propstype) {                                                        \
+      case GST_PROPS_INT_TYPE:                                                 \
+        *(va_arg (var_args, gint*)) = entry->data.int_data;                    \
+        break;                                                                 \
+      case GST_PROPS_INT_RANGE_TYPE:                                           \
+        *(va_arg (var_args, gint*)) = entry->data.int_range_data.min;          \
+        *(va_arg (var_args, gint*)) = entry->data.int_range_data.max;          \
+        break;                                                                 \
+      case GST_PROPS_FLOAT_TYPE:                                               \
+        *(va_arg (var_args, gfloat*)) = entry->data.float_data;                        \
+        break;                                                                 \
+      case GST_PROPS_FLOAT_RANGE_TYPE:                                         \
+        *(va_arg (var_args, gfloat*)) = entry->data.float_range_data.min;      \
+        *(va_arg (var_args, gfloat*)) = entry->data.float_range_data.max;      \
+        break;                                                                 \
+      case GST_PROPS_FOURCC_TYPE:                                              \
+        *(va_arg (var_args, guint32*)) = entry->data.fourcc_data;              \
+        break;                                                                 \
+      case GST_PROPS_BOOL_TYPE:                                                        \
+        *(va_arg (var_args, gboolean*)) = entry->data.bool_data;               \
+        break;                                                                 \
+      case GST_PROPS_STRING_TYPE:                                              \
+        *(va_arg (var_args, gchar**)) = entry->data.string_data.string;                \
+        break;                                                                 \
+      case GST_PROPS_LIST_TYPE:                                                        \
+        *(va_arg (var_args, GList**)) = entry->data.list_data.entries;         \
+        break;                                                                 \
+      default:                                                                 \
+        *result = FALSE;                                                       \
+        break;                                                                 \
+    }                                                                          \
+  }                                                                            \
+} G_STMT_END
+
 static GstPropsEntry*
 gst_props_alloc_entry (void)
 {
@@ -169,10 +252,10 @@ static void
 gst_props_entry_destroy (GstPropsEntry *entry)
 {
   switch (entry->propstype) {
-    case GST_PROPS_STRING_ID:          
+    case GST_PROPS_STRING_TYPE:                
       g_free (entry->data.string_data.string);
       break;                           
-    case GST_PROPS_LIST_ID:            
+    case GST_PROPS_LIST_TYPE:          
     {
       GList *entries = entry->data.list_data.entries;
 
@@ -275,7 +358,7 @@ gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
   gint new_min, new_max, old_min, old_max;
   gboolean can_merge = FALSE;
 
-  if (newentry->propstype == GST_PROPS_INT_ID) {
+  if (newentry->propstype == GST_PROPS_INT_TYPE) {
     new_min = newentry->data.int_data;
     new_max = newentry->data.int_data;
   } else {
@@ -283,7 +366,7 @@ gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
     new_max = newentry->data.int_range_data.max;
   }
 
-  if (oldentry->propstype == GST_PROPS_INT_ID) {
+  if (oldentry->propstype == GST_PROPS_INT_TYPE) {
     old_min = oldentry->data.int_data;
     old_max = oldentry->data.int_data;
   } else {
@@ -312,10 +395,10 @@ gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
 
   if (can_merge) {
     if (new_min == new_max) {
-      newentry->propstype = GST_PROPS_INT_ID;
+      newentry->propstype = GST_PROPS_INT_TYPE;
       newentry->data.int_data = new_min;
     } else {
-      newentry->propstype = GST_PROPS_INT_RANGE_ID;
+      newentry->propstype = GST_PROPS_INT_RANGE_TYPE;
       newentry->data.int_range_data.min = new_min;
       newentry->data.int_range_data.max = new_max;
     }
@@ -411,27 +494,27 @@ gst_props_newv (const gchar *firstname, va_list var_args)
     GST_PROPS_ENTRY_FILL (entry, var_args);
 
     switch (entry->propstype) {
-      case GST_PROPS_INT_ID:
-      case GST_PROPS_INT_RANGE_ID:
+      case GST_PROPS_INT_TYPE:
+      case GST_PROPS_INT_RANGE_TYPE:
        entry_type = GST_PROPS_LIST_T_INTS;
        break;
-      case GST_PROPS_FLOAT_ID:
-      case GST_PROPS_FLOAT_RANGE_ID:
+      case GST_PROPS_FLOAT_TYPE:
+      case GST_PROPS_FLOAT_RANGE_TYPE:
        entry_type = GST_PROPS_LIST_T_FLOATS;
        break;
-      case GST_PROPS_FOURCC_ID:
-      case GST_PROPS_BOOL_ID:
-      case GST_PROPS_STRING_ID:
+      case GST_PROPS_FOURCC_TYPE:
+      case GST_PROPS_BOOL_TYPE:
+      case GST_PROPS_STRING_TYPE:
        entry_type = GST_PROPS_LIST_T_MISC;
        break;
-      case GST_PROPS_LIST_ID:
+      case GST_PROPS_LIST_TYPE:
        g_return_val_if_fail (inlist == FALSE, NULL);
        inlist = TRUE;
        list_entry = entry;
        list_type = GST_PROPS_LIST_T_UNSET;
        list_entry->data.list_data.entries = NULL;
        break;
-      case GST_PROPS_END_ID:
+      case GST_PROPS_END_TYPE:
        g_return_val_if_fail (inlist == TRUE, NULL);
 
        /* if list was of size 1, replace the list by a the item it contains */
@@ -605,10 +688,10 @@ gst_props_entry_copy (GstPropsEntry *entry)
 
   newentry = gst_props_alloc_entry ();
   memcpy (newentry, entry, sizeof (GstPropsEntry));
-  if (entry->propstype == GST_PROPS_LIST_ID) {
+  if (entry->propstype == GST_PROPS_LIST_TYPE) {
     newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
   }
-  else if (entry->propstype == GST_PROPS_STRING_ID) {
+  else if (entry->propstype == GST_PROPS_STRING_TYPE) {
     newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
   }
 
@@ -679,8 +762,8 @@ gst_props_copy_on_write (GstProps *props)
   return new;
 }
 
-static GstPropsEntry*
-gst_props_get_entry_func (GstProps *props, const gchar *name)
+const GstPropsEntry*
+gst_props_get_entry (GstProps *props, const gchar *name)
 {
   GList *lentry;
   GQuark quark;
@@ -703,134 +786,168 @@ gst_props_get_entry_func (GstProps *props, const gchar *name)
 gboolean
 gst_props_has_property (GstProps *props, const gchar *name)
 {
-  return (gst_props_get_entry_func (props, name) != NULL);
+  return (gst_props_get_entry (props, name) != NULL);
 }
 
-/**
- * gst_props_get_int:
- * @props: the props to get the int value from
- * @name: the name of the props entry to get.
- *
- * Get the named entry as an integer.
- *
- * Returns: the integer value of the named entry, 0 if not found.
- */
-gint
-gst_props_get_int (GstProps *props, const gchar *name)
+gboolean
+gst_props_has_property_typed (GstProps *props, const gchar *name, GstPropsType type)
 {
-  GstPropsEntry *thisentry;
+  const GstPropsEntry *entry;
 
-  thisentry = gst_props_get_entry_func (props, name);
+  entry = gst_props_get_entry (props, name);
+  if (!entry) 
+    return FALSE;
 
-  if (thisentry) {
-    return thisentry->data.int_data;
-  }
-  else {
-    g_warning ("props: property %s not found", name);
-  }
-  return 0;
+  return (entry->propstype == type);
 }
 
-/**
- * gst_props_get_float:
- * @props: the props to get the float value from
- * @name: the name of the props entry to get.
- *
- * Get the named entry as a float.
- *
- * Returns: the float value of the named entry, 0.0 if not found.
- */
-gfloat
-gst_props_get_float (GstProps *props, const gchar *name)
+gboolean
+gst_props_has_fixed_property (GstProps *props, const gchar *name)
 {
-  GstPropsEntry *thisentry;
+  const GstPropsEntry *entry;
 
-  thisentry = gst_props_get_entry_func (props, name);
+  entry = gst_props_get_entry (props, name);
+  if (!entry) 
+    return FALSE;
 
-  if (thisentry) {
-    return thisentry->data.float_data;
-  }
-  else {
-    g_warning ("props: property %s not found", name);
-  }
-  return 0.0F;
+  return !GST_PROPS_ENTRY_IS_VARIABLE (entry);
 }
 
-/**
- * gst_props_get_fourcc_int:
- * @props: the props to get the fourcc value from
- * @name: the name of the props entry to get.
- *
- * Get the named entry as a gulong fourcc.
- *
- * Returns: the fourcc value of the named entry, 0 if not found.
- */
-gulong
-gst_props_get_fourcc_int (GstProps *props, const gchar *name)
+GstPropsType
+gst_props_entry_get_type (const GstPropsEntry *entry)
 {
-  GstPropsEntry *thisentry;
+  g_return_val_if_fail (entry != NULL, GST_PROPS_INVALID_TYPE);
 
-  thisentry = gst_props_get_entry_func (props, name);
+  return entry->propstype;
+}
 
-  if (thisentry) {
-    return thisentry->data.fourcc_data;
-  }
-  else {
-    g_warning ("props: property %s not found", name);
-  }
-  return 0;
+const gchar*
+gst_props_entry_get_name (const GstPropsEntry *entry)
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+
+  return g_quark_to_string (entry->propid);
 }
 
-/**
- * gst_props_get_boolean:
- * @props: the props to get the fourcc value from
- * @name: the name of the props entry to get.
- *
- * Get the named entry as a boolean value.
- *
- * Returns: the boolean value of the named entry, 0 if not found.
- */
 gboolean
-gst_props_get_boolean (GstProps *props, const gchar *name)
+gst_props_entry_is_fixed (const GstPropsEntry *entry)
+{
+  g_return_val_if_fail (entry != NULL, FALSE);
+
+  return !GST_PROPS_ENTRY_IS_VARIABLE (entry);
+}
+
+static gboolean
+gst_props_entry_getv (const GstPropsEntry *entry, gboolean safe, va_list var_args)
 {
-  GstPropsEntry *thisentry;
+  gboolean result;
 
-  thisentry = gst_props_get_entry_func (props, name);
+  GST_PROPS_ENTRY_READ (entry, var_args, safe, &result);
 
-  if (thisentry) {
-    return thisentry->data.bool_data;
-  }
-  else {
-    g_warning ("props: property %s not found", name);
-  }
-  return 0;
+  return result;
 }
 
-/**
- * gst_props_get_string:
- * @props: the props to get the fourcc value from
- * @name: the name of the props entry to get.
- *
- * Get the named entry as a string value.
- *
- * Returns: the string value of the named entry, NULL if not found.
- */
-const gchar*
-gst_props_get_string (GstProps *props, const gchar *name)
+gboolean
+gst_props_entry_get (const GstPropsEntry *entry, ...)
+{
+  gboolean result;
+  va_list var_args;
+
+  g_return_val_if_fail (entry != NULL, FALSE);
+
+  va_start (var_args, entry);
+  result = gst_props_entry_getv (entry, FALSE, var_args);
+  va_end (var_args);
+
+  return result;
+}
+
+static gboolean
+gst_props_entry_get_safe (const GstPropsEntry *entry, ...)
 {
-  GstPropsEntry *thisentry;
+  gboolean result;
+  va_list var_args;
 
-  thisentry = gst_props_get_entry_func (props, name);
+  g_return_val_if_fail (entry != NULL, FALSE);
 
-  if (thisentry) {
-    return thisentry->data.string_data.string;
-  }
-  else {
-    g_warning ("props: property %s not found", name);
+  va_start (var_args, entry);
+  result = gst_props_entry_getv (entry, TRUE, var_args);
+  va_end (var_args);
+
+  return result;
+}
+
+gboolean
+gst_props_get (GstProps *props, gchar *first_name, ...)
+{
+  va_list var_args;
+
+  va_start (var_args, first_name);
+
+  while (first_name) {
+    const GstPropsEntry *entry = gst_props_get_entry (props, first_name);
+    gboolean result;
+
+    if (!entry) return FALSE;
+    GST_PROPS_ENTRY_READ (entry, var_args, FALSE, &result);
+    if (!result) return FALSE;
+
+    first_name = va_arg (var_args, gchar *);
   }
-  return NULL;
+  va_end (var_args);
+  
+  return TRUE;
+}
+
+gboolean
+gst_props_entry_get_int (const GstPropsEntry *entry, gint *val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_INT_TYPE, val);
+}
+
+gboolean
+gst_props_entry_get_float (const GstPropsEntry *entry, gfloat *val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_FLOAT_TYPE, val);
+}
+
+gboolean
+gst_props_entry_get_fourcc_int (const GstPropsEntry *entry, guint32 *val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_FOURCC_TYPE, val);
+}
+
+gboolean
+gst_props_entry_get_boolean (const GstPropsEntry *entry, gboolean *val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_BOOL_TYPE, val);
+}
+
+gboolean
+gst_props_entry_get_string (const GstPropsEntry *entry, const gchar **val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_STRING_TYPE, val);
+}
+
+gboolean
+gst_props_entry_get_int_range (const GstPropsEntry *entry, gint *min, gint *max)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_INT_RANGE_TYPE, min, max);
 }
 
+gboolean
+gst_props_entry_get_float_range (const GstPropsEntry *entry, gfloat *min, gfloat *max)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_FLOAT_RANGE_TYPE, min, max);
+}
+
+gboolean
+gst_props_entry_get_list (const GstPropsEntry *entry, const GList **val)
+{
+  return gst_props_entry_get_safe (entry, GST_PROPS_LIST_TYPE, val);
+}
+
+
 /**
  * gst_props_merge:
  * @props: the property to merge into
@@ -887,12 +1004,12 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
   GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s", g_quark_to_string (entry1->propid),
                             g_quark_to_string (entry2->propid));
 
-  if (entry2->propstype == GST_PROPS_LIST_ID && entry1->propstype != GST_PROPS_LIST_ID) {
+  if (entry2->propstype == GST_PROPS_LIST_TYPE && entry1->propstype != GST_PROPS_LIST_TYPE) {
     return gst_props_entry_check_list_compatibility (entry1, entry2);
   }
 
   switch (entry1->propstype) {
-    case GST_PROPS_LIST_ID:
+    case GST_PROPS_LIST_TYPE:
     {
       GList *entrylist = entry1->data.list_data.entries;
       gboolean valid = TRUE;    /* innocent until proven guilty */
@@ -907,79 +1024,79 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
       
       return valid;
     }
-    case GST_PROPS_INT_RANGE_ID:
+    case GST_PROPS_INT_RANGE_TYPE:
       switch (entry2->propstype) {
        /* a - b   <--->   a - c */
-        case GST_PROPS_INT_RANGE_ID:
+        case GST_PROPS_INT_RANGE_TYPE:
          return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
                  entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
         default:
          break;
       }
       break;
-    case GST_PROPS_FLOAT_RANGE_ID:
+    case GST_PROPS_FLOAT_RANGE_TYPE:
       switch (entry2->propstype) {
        /* a - b   <--->   a - c */
-        case GST_PROPS_FLOAT_RANGE_ID:
+        case GST_PROPS_FLOAT_RANGE_TYPE:
          return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
                  entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
         default:
          break;
       }
       break;
-    case GST_PROPS_FOURCC_ID:
+    case GST_PROPS_FOURCC_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a */
-        case GST_PROPS_FOURCC_ID:
-          GST_DEBUG(GST_CAT_PROPERTIES,"\"%4.4s\" <--> \"%4.4s\" ?",
+        case GST_PROPS_FOURCC_TYPE:
+          GST_DEBUG(GST_CAT_PROPERTIES,"\"%4.4s\" <--> \"%4.4s\" ?\n",
                          (char*) &entry2->data.fourcc_data, (char*) &entry1->data.fourcc_data);
          return (entry2->data.fourcc_data == entry1->data.fourcc_data);
         default:
          break;
       }
       break;
-    case GST_PROPS_INT_ID:
+    case GST_PROPS_INT_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a - d */
-        case GST_PROPS_INT_RANGE_ID:
-          GST_DEBUG(GST_CAT_PROPERTIES,"%d <= %d <= %d ?",entry2->data.int_range_data.min,
+        case GST_PROPS_INT_RANGE_TYPE:
+          GST_DEBUG(GST_CAT_PROPERTIES,"%d <= %d <= %d ?\n",entry2->data.int_range_data.min,
                     entry1->data.int_data,entry2->data.int_range_data.max);
          return (entry2->data.int_range_data.min <= entry1->data.int_data &&
                  entry2->data.int_range_data.max >= entry1->data.int_data);
        /* b   <--->   a */
-        case GST_PROPS_INT_ID:
-          GST_DEBUG(GST_CAT_PROPERTIES,"%d == %d ?",entry1->data.int_data,entry2->data.int_data);
+        case GST_PROPS_INT_TYPE:
+          GST_DEBUG(GST_CAT_PROPERTIES,"%d == %d ?\n",entry1->data.int_data,entry2->data.int_data);
          return (entry2->data.int_data == entry1->data.int_data);
         default:
          break;
       }
       break;
-    case GST_PROPS_FLOAT_ID:
+    case GST_PROPS_FLOAT_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a - d */
-        case GST_PROPS_FLOAT_RANGE_ID:
+        case GST_PROPS_FLOAT_RANGE_TYPE:
          return (entry2->data.float_range_data.min <= entry1->data.float_data &&
                  entry2->data.float_range_data.max >= entry1->data.float_data);
        /* b   <--->   a */
-        case GST_PROPS_FLOAT_ID:
+        case GST_PROPS_FLOAT_TYPE:
          return (entry2->data.float_data == entry1->data.float_data);
         default:
          break;
       }
       break;
-    case GST_PROPS_BOOL_ID:
+    case GST_PROPS_BOOL_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_BOOL_ID:
+        case GST_PROPS_BOOL_TYPE:
           return (entry2->data.bool_data == entry1->data.bool_data);
         default:
          break;
       }
-    case GST_PROPS_STRING_ID:
+    case GST_PROPS_STRING_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_STRING_ID:
-          GST_DEBUG(GST_CAT_PROPERTIES,"\"%s\" <--> \"%s\" ?",
+        case GST_PROPS_STRING_TYPE:
+          GST_DEBUG(GST_CAT_PROPERTIES,"\"%s\" <--> \"%s\" ?\n",
                          entry2->data.string_data.string, entry1->data.string_data.string);
           return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
         default:
@@ -1065,9 +1182,9 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
 
   /* try to move the ranges and lists first */
   switch (entry2->propstype) {
-    case GST_PROPS_INT_RANGE_ID:
-    case GST_PROPS_FLOAT_RANGE_ID:
-    case GST_PROPS_LIST_ID:
+    case GST_PROPS_INT_RANGE_TYPE:
+    case GST_PROPS_FLOAT_RANGE_TYPE:
+    case GST_PROPS_LIST_TYPE:
     {
       GstPropsEntry *temp;
 
@@ -1080,7 +1197,7 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
   }
 
   switch (entry1->propstype) {
-    case GST_PROPS_LIST_ID:
+    case GST_PROPS_LIST_TYPE:
     {
       GList *entrylist = entry1->data.list_data.entries;
       GList *intersection = NULL;
@@ -1092,7 +1209,7 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
        intersectentry = gst_props_entry_intersect (entry2, entry);
 
        if (intersectentry) {
-         if (intersectentry->propstype == GST_PROPS_LIST_ID) {
+         if (intersectentry->propstype == GST_PROPS_LIST_TYPE) {
            intersection = g_list_concat (intersection, intersectentry->data.list_data.entries);
            /* set the list to NULL because the entries are concatenated to the above
             * list and we don't want to free them */
@@ -1115,16 +1232,16 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
        else {
          result = gst_props_alloc_entry ();
          result->propid = entry1->propid;
-         result->propstype = GST_PROPS_LIST_ID;
+         result->propstype = GST_PROPS_LIST_TYPE;
          result->data.list_data.entries = g_list_reverse (intersection);
        }
       }
       return result;
     }
-    case GST_PROPS_INT_RANGE_ID:
+    case GST_PROPS_INT_RANGE_TYPE:
       switch (entry2->propstype) {
        /* a - b   <--->   a - c */
-        case GST_PROPS_INT_RANGE_ID:
+        case GST_PROPS_INT_RANGE_TYPE:
         {
          gint lower = MAX (entry1->data.int_range_data.min, entry2->data.int_range_data.min);
          gint upper = MIN (entry1->data.int_range_data.max, entry2->data.int_range_data.max);
@@ -1134,27 +1251,27 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
            result->propid = entry1->propid;
 
            if (lower == upper) {
-             result->propstype = GST_PROPS_INT_ID;
+             result->propstype = GST_PROPS_INT_TYPE;
              result->data.int_data = lower;
            }
            else {
-             result->propstype = GST_PROPS_INT_RANGE_ID;
+             result->propstype = GST_PROPS_INT_RANGE_TYPE;
              result->data.int_range_data.min = lower;
              result->data.int_range_data.max = upper;
            }
          }
          break;
        }
-        case GST_PROPS_LIST_ID:
+        case GST_PROPS_LIST_TYPE:
         {
           GList *entries = entry2->data.list_data.entries;
           result = gst_props_alloc_entry ();
           result->propid = entry1->propid;
-          result->propstype = GST_PROPS_LIST_ID;
+          result->propstype = GST_PROPS_LIST_TYPE;
           result->data.list_data.entries = NULL;
           while (entries) {
             GstPropsEntry * this = (GstPropsEntry *)entries->data;
-            if (this->propstype != GST_PROPS_INT_ID) {
+            if (this->propstype != GST_PROPS_INT_TYPE) {
               /* no hope, this list doesn't even contain ints! */
               gst_props_entry_destroy (result);
               result = NULL;
@@ -1169,7 +1286,7 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
           }
           break;
         }
-        case GST_PROPS_INT_ID:
+        case GST_PROPS_INT_TYPE:
         {
          if (entry1->data.int_range_data.min <= entry2->data.int_data && 
              entry1->data.int_range_data.max >= entry2->data.int_data) {
@@ -1181,10 +1298,10 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
          break;
       }
       break;
-    case GST_PROPS_FLOAT_RANGE_ID:
+    case GST_PROPS_FLOAT_RANGE_TYPE:
       switch (entry2->propstype) {
        /* a - b   <--->   a - c */
-        case GST_PROPS_FLOAT_RANGE_ID:
+        case GST_PROPS_FLOAT_RANGE_TYPE:
         {
          gfloat lower = MAX (entry1->data.float_range_data.min, entry2->data.float_range_data.min);
          gfloat upper = MIN (entry1->data.float_range_data.max, entry2->data.float_range_data.max);
@@ -1194,18 +1311,18 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
            result->propid = entry1->propid;
 
            if (lower == upper) {
-             result->propstype = GST_PROPS_FLOAT_ID;
+             result->propstype = GST_PROPS_FLOAT_TYPE;
              result->data.float_data = lower;
            }
            else {
-             result->propstype = GST_PROPS_FLOAT_RANGE_ID;
+             result->propstype = GST_PROPS_FLOAT_RANGE_TYPE;
              result->data.float_range_data.min = lower;
              result->data.float_range_data.max = upper;
            }
          }
          break;
        }
-        case GST_PROPS_FLOAT_ID:
+        case GST_PROPS_FLOAT_TYPE:
          if (entry1->data.float_range_data.min <= entry2->data.float_data && 
              entry1->data.float_range_data.max >= entry2->data.float_data) {
             result = gst_props_entry_copy (entry2);
@@ -1214,49 +1331,49 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
          break;
       }
       break;
-    case GST_PROPS_FOURCC_ID:
+    case GST_PROPS_FOURCC_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a */
-        case GST_PROPS_FOURCC_ID:
+        case GST_PROPS_FOURCC_TYPE:
           if (entry1->data.fourcc_data == entry2->data.fourcc_data)
            result = gst_props_entry_copy (entry1);
         default:
          break;
       }
       break;
-    case GST_PROPS_INT_ID:
+    case GST_PROPS_INT_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a */
-        case GST_PROPS_INT_ID:
+        case GST_PROPS_INT_TYPE:
           if (entry1->data.int_data == entry2->data.int_data)
            result = gst_props_entry_copy (entry1);
         default:
          break;
       }
       break;
-    case GST_PROPS_FLOAT_ID:
+    case GST_PROPS_FLOAT_TYPE:
       switch (entry2->propstype) {
        /* b   <--->   a */
-        case GST_PROPS_FLOAT_ID:
+        case GST_PROPS_FLOAT_TYPE:
           if (entry1->data.float_data == entry2->data.float_data)
            result = gst_props_entry_copy (entry1);
         default:
          break;
       }
       break;
-    case GST_PROPS_BOOL_ID:
+    case GST_PROPS_BOOL_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_BOOL_ID:
+        case GST_PROPS_BOOL_TYPE:
           if (entry1->data.bool_data == entry2->data.bool_data)
            result = gst_props_entry_copy (entry1);
         default:
          break;
       }
-    case GST_PROPS_STRING_ID:
+    case GST_PROPS_STRING_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_STRING_ID:
+        case GST_PROPS_STRING_TYPE:
           if (!strcmp (entry1->data.string_data.string, entry2->data.string_data.string))
            result = gst_props_entry_copy (entry1);
         default:
@@ -1392,7 +1509,7 @@ gst_props_normalize (GstProps *props)
   while (entries) {
     GstPropsEntry *entry = (GstPropsEntry *) entries->data;
 
-    if (entry->propstype == GST_PROPS_LIST_ID) {
+    if (entry->propstype == GST_PROPS_LIST_TYPE) {
       GList *list_entries = entry->data.list_data.entries;
 
       while (list_entries) {
@@ -1443,14 +1560,14 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
   gchar *str;
 
   switch (entry->propstype) {
-    case GST_PROPS_INT_ID
+    case GST_PROPS_INT_TYPE
       subtree = xmlNewChild (parent, NULL, "int", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       str = g_strdup_printf ("%d", entry->data.int_data);
       xmlNewProp (subtree, "value", str);
       g_free(str);
       break;
-    case GST_PROPS_INT_RANGE_ID
+    case GST_PROPS_INT_RANGE_TYPE
       subtree = xmlNewChild (parent, NULL, "range", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       str = g_strdup_printf ("%d", entry->data.int_range_data.min);
@@ -1460,14 +1577,14 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
       xmlNewProp (subtree, "max", str);
       g_free(str);
       break;
-    case GST_PROPS_FLOAT_ID
+    case GST_PROPS_FLOAT_TYPE
       subtree = xmlNewChild (parent, NULL, "float", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       str = g_strdup_printf ("%f", entry->data.float_data);
       xmlNewProp (subtree, "value", str);
       g_free(str);
       break;
-    case GST_PROPS_FLOAT_RANGE_ID
+    case GST_PROPS_FLOAT_RANGE_TYPE
       subtree = xmlNewChild (parent, NULL, "floatrange", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       str = g_strdup_printf ("%f", entry->data.float_range_data.min);
@@ -1477,7 +1594,7 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
       xmlNewProp (subtree, "max", str);
       g_free(str);
       break;
-    case GST_PROPS_FOURCC_ID
+    case GST_PROPS_FOURCC_TYPE
       str = g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data);
       xmlAddChild (parent, xmlNewComment (str));
       g_free(str);
@@ -1487,12 +1604,12 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
       xmlNewProp (subtree, "hexvalue", str);
       g_free(str);
       break;
-    case GST_PROPS_BOOL_ID
+    case GST_PROPS_BOOL_TYPE
       subtree = xmlNewChild (parent, NULL, "boolean", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       xmlNewProp (subtree, "value", (entry->data.bool_data ?  "true" : "false"));
       break;
-    case GST_PROPS_STRING_ID
+    case GST_PROPS_STRING_TYPE
       subtree = xmlNewChild (parent, NULL, "string", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       xmlNewProp (subtree, "value", entry->data.string_data.string);
@@ -1528,7 +1645,7 @@ gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
     GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
 
     switch (entry->propstype) {
-      case GST_PROPS_LIST_ID
+      case GST_PROPS_LIST_TYPE
         subtree = xmlNewChild (parent, NULL, "list", NULL);
         xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
         g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
@@ -1552,7 +1669,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
   entry = gst_props_alloc_entry ();
 
   if (!strcmp(field->name, "int")) {
-    entry->propstype = GST_PROPS_INT_ID;
+    entry->propstype = GST_PROPS_INT_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1561,7 +1678,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "range")) {
-    entry->propstype = GST_PROPS_INT_RANGE_ID;
+    entry->propstype = GST_PROPS_INT_RANGE_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1573,7 +1690,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "float")) {
-    entry->propstype = GST_PROPS_FLOAT_ID;
+    entry->propstype = GST_PROPS_FLOAT_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1582,7 +1699,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "floatrange")) {
-    entry->propstype = GST_PROPS_FLOAT_RANGE_ID;
+    entry->propstype = GST_PROPS_FLOAT_RANGE_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1594,7 +1711,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "boolean")) {
-    entry->propstype = GST_PROPS_BOOL_ID;
+    entry->propstype = GST_PROPS_BOOL_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1604,7 +1721,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "fourcc")) {
-    entry->propstype = GST_PROPS_FOURCC_ID;
+    entry->propstype = GST_PROPS_FOURCC_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1613,7 +1730,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "string")) {
-    entry->propstype = GST_PROPS_STRING_ID;
+    entry->propstype = GST_PROPS_STRING_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
@@ -1655,7 +1772,7 @@ gst_props_load_thyself (xmlNodePtr parent)
       prop = xmlGetProp (field, "name");
       entry->propid = g_quark_from_string (prop);
       g_free (prop);
-      entry->propstype = GST_PROPS_LIST_ID;
+      entry->propstype = GST_PROPS_LIST_TYPE;
       entry->data.list_data.entries = NULL;
 
       while (subfield) {
index ab63efa..9343927 100644 (file)
 
 #include <gst/gstconfig.h>
 
-#include <glib.h>
+#include <glib-object.h>
 
 typedef struct _GstProps GstProps;
+extern GType _gst_props_type;
+
+#define GST_TYPE_PROPS (_get_props_type)
 
 typedef enum {
-   GST_PROPS_END_ID = 0,
-   GST_PROPS_INT_ID,
-   GST_PROPS_FLOAT_ID,
-   GST_PROPS_FOURCC_ID,
-   GST_PROPS_BOOL_ID,
-   GST_PROPS_STRING_ID,
+   GST_PROPS_END_TYPE = 0,
+
+   GST_PROPS_INVALID_TYPE,
+
+   GST_PROPS_INT_TYPE,
+   GST_PROPS_FLOAT_TYPE,
+   GST_PROPS_FOURCC_TYPE,
+   GST_PROPS_BOOL_TYPE,
+   GST_PROPS_STRING_TYPE,
 
-   GST_PROPS_VAR_ID,   /* after this marker start the variable properties */
+   GST_PROPS_VAR_TYPE,   /* after this marker start the variable properties */
 
-   GST_PROPS_LIST_ID,
-   GST_PROPS_FLOAT_RANGE_ID,
-   GST_PROPS_INT_RANGE_ID,
+   GST_PROPS_LIST_TYPE,
+   GST_PROPS_FLOAT_RANGE_TYPE,
+   GST_PROPS_INT_RANGE_TYPE,
 
-   GST_PROPS_LAST_ID = GST_PROPS_END_ID + 16,
-} GstPropsId;
+   GST_PROPS_LAST_TYPE = GST_PROPS_END_TYPE + 16,
+} GstPropsType;
 
 #define GST_MAKE_FOURCC(a,b,c,d)       ((a)|(b)<<8|(c)<<16|(d)<<24)
 #define GST_STR_FOURCC(f)              (((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24))
 
-#define GST_PROPS_LIST(a...)           GST_PROPS_LIST_ID,##a,NULL
-#define GST_PROPS_INT(a)               GST_PROPS_INT_ID,(a)
-#define GST_PROPS_INT_RANGE(a,b)       GST_PROPS_INT_RANGE_ID,(a),(b)
-#define GST_PROPS_FLOAT(a)             GST_PROPS_FLOAT_ID,(a)
-#define GST_PROPS_FLOAT_RANGE(a,b)     GST_PROPS_FLOAT_RANGE_ID,(a),(b)
-#define GST_PROPS_FOURCC(a)            GST_PROPS_FOURCC_ID,(a)
-#define GST_PROPS_BOOLEAN(a)           GST_PROPS_BOOL_ID,(a)
-#define GST_PROPS_STRING(a)            GST_PROPS_STRING_ID,(a)
+#define GST_PROPS_LIST(a...)           GST_PROPS_LIST_TYPE,##a,NULL
+#define GST_PROPS_INT(a)               GST_PROPS_INT_TYPE,(a)
+#define GST_PROPS_INT_RANGE(a,b)       GST_PROPS_INT_RANGE_TYPE,(a),(b)
+#define GST_PROPS_FLOAT(a)             GST_PROPS_FLOAT_TYPE,(a)
+#define GST_PROPS_FLOAT_RANGE(a,b)     GST_PROPS_FLOAT_RANGE_TYPE,(a),(b)
+#define GST_PROPS_FOURCC(a)            GST_PROPS_FOURCC_TYPE,(a)
+#define GST_PROPS_BOOLEAN(a)           GST_PROPS_BOOL_TYPE,(a)
+#define GST_PROPS_STRING(a)            GST_PROPS_STRING_TYPE,(a)
 
 #define GST_PROPS_INT_POSITIVE         GST_PROPS_INT_RANGE(0,G_MAXINT)
 #define GST_PROPS_INT_NEGATIVE         GST_PROPS_INT_RANGE(G_MININT,0)
 #define GST_PROPS_INT_ANY              GST_PROPS_INT_RANGE(G_MININT,G_MAXINT)
 
+typedef struct _GstPropsEntry GstPropsEntry;
 
 struct _GstProps {
   gint refcount;
-  GMutex *lock;
   gboolean fixed;
 
   GList *properties;           /* real properties for this property */
 };
 
 /* initialize the subsystem */
-void           _gst_props_initialize           (void);
+void                   _gst_props_initialize           (void);
+
+GstProps*              gst_props_new                   (const gchar *firstname, ...);
+GstProps*              gst_props_newv                  (const gchar *firstname, va_list var_args);
+
+void                   gst_props_unref                 (GstProps *props);
+void                   gst_props_ref                   (GstProps *props);
+void                   gst_props_destroy               (GstProps *props);
 
-GstProps*      gst_props_new                   (const gchar *firstname, ...);
-GstProps*      gst_props_newv                  (const gchar *firstname, va_list var_args);
+void                   gst_props_debug                 (GstProps *props);
 
-void            gst_props_unref                 (GstProps *props);
-void            gst_props_ref                   (GstProps *props);
-void            gst_props_destroy               (GstProps *props);
+GstProps*              gst_props_copy                  (GstProps *props);
+GstProps*              gst_props_copy_on_write         (GstProps *props);
 
-void            gst_props_debug                (GstProps *props);
+GstProps*              gst_props_merge                 (GstProps *props, GstProps *tomerge);
 
-GstProps*       gst_props_copy                  (GstProps *props);
-GstProps*       gst_props_copy_on_write         (GstProps *props);
+gboolean               gst_props_check_compatibility   (GstProps *fromprops, GstProps *toprops);
+GstProps*              gst_props_intersect             (GstProps *props1, GstProps *props2);
+GList*                         gst_props_normalize             (GstProps *props);
 
-GstProps*      gst_props_merge                 (GstProps *props, GstProps *tomerge);
+GstProps*              gst_props_set                   (GstProps *props, const gchar *name, ...);
+gboolean               gst_props_get                   (GstProps *props, gchar *first_name, ...);
 
-gboolean       gst_props_check_compatibility   (GstProps *fromprops, GstProps *toprops);
-GstProps*      gst_props_intersect             (GstProps *props1, GstProps *props2);
-GList*                 gst_props_normalize             (GstProps *props);
+gboolean               gst_props_has_property          (GstProps *props, const gchar *name);
+gboolean               gst_props_has_property_typed    (GstProps *props, const gchar *name, GstPropsType type);
+gboolean               gst_props_has_fixed_property    (GstProps *props, const gchar *name);
 
-GstProps*      gst_props_set                   (GstProps *props, const gchar *name, ...);
 
-gboolean       gst_props_has_property          (GstProps *props, const gchar *name);
+/* working with props entries */
+const GstPropsEntry*   gst_props_get_entry             (GstProps *props, const gchar *name);
+GstPropsType           gst_props_entry_get_type        (const GstPropsEntry *entry);
+const gchar*           gst_props_entry_get_name        (const GstPropsEntry *entry);
+gboolean               gst_props_entry_is_fixed        (const GstPropsEntry *entry);
+
+gboolean               gst_props_entry_get             (const GstPropsEntry *props, ...);
+
+gboolean               gst_props_entry_get_int         (const GstPropsEntry *entry, gint *val);
+gboolean               gst_props_entry_get_float       (const GstPropsEntry *entry, gfloat *val);
+gboolean               gst_props_entry_get_fourcc_int  (const GstPropsEntry *entry, guint32 *val);
+gboolean               gst_props_entry_get_boolean     (const GstPropsEntry *entry, gboolean *val);
+gboolean               gst_props_entry_get_string      (const GstPropsEntry *entry, const gchar **val);
+gboolean               gst_props_entry_get_int_range   (const GstPropsEntry *entry, gint *min, gint *max);
+gboolean               gst_props_entry_get_float_range (const GstPropsEntry *entry, gfloat *min, gfloat *max);
+gboolean               gst_props_entry_get_list        (const GstPropsEntry *entry, const GList **val);
 
-gint           gst_props_get_int               (GstProps *props, const gchar *name);
-gfloat                 gst_props_get_float             (GstProps *props, const gchar *name);
-gulong         gst_props_get_fourcc_int        (GstProps *props, const gchar *name);
-gboolean       gst_props_get_boolean           (GstProps *props, const gchar *name);
-const gchar*   gst_props_get_string            (GstProps *props, const gchar *name);
 
 #ifndef GST_DISABLE_LOADSAVE
-xmlNodePtr     gst_props_save_thyself          (GstProps *props, xmlNodePtr parent);
-GstProps*      gst_props_load_thyself          (xmlNodePtr parent);
+xmlNodePtr             gst_props_save_thyself          (GstProps *props, xmlNodePtr parent);
+GstProps*              gst_props_load_thyself          (xmlNodePtr parent);
 #endif
 
+
+
 #endif /* __GST_PROPS_H__ */
diff --git a/gst/gstpropsprivate.h b/gst/gstpropsprivate.h
deleted file mode 100644 (file)
index b7c4512..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *
- * gstpropsprivate.h: Private header for properties subsystem
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __GST_PROPS_PRIV_H__
-#define __GST_PROPS_PRIV_H__
-
-#include <gst/gstprops.h>
-
-#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_ID)
-
-typedef struct _GstPropsEntry GstPropsEntry;
-
-struct _GstPropsEntry {
-  GQuark    propid;
-  GstPropsId propstype;                
-
-  union {
-    /* flat values */
-    gboolean bool_data;
-    guint32  fourcc_data;
-    gint     int_data;
-    gfloat   float_data;
-
-    /* structured values */
-    struct {
-      GList *entries;
-    } list_data;
-    struct {
-      gchar *string;
-    } string_data;
-    struct {
-      gint min;
-      gint max;
-    } int_range_data;
-    struct {
-      gfloat min;
-      gfloat max;
-    } float_range_data;
-  } data;
-};
-
-#endif /* __GST_PROPS_PRIV_H__ */
index 3540743..cf8ec85 100644 (file)
@@ -83,7 +83,6 @@ static GstBuffer *            gst_queue_get                   (GstPad *pad);
 static GstBufferPool*          gst_queue_get_bufferpool        (GstPad *pad);
        
 static void                    gst_queue_locked_flush                  (GstQueue *queue);
-static void                    gst_queue_flush                 (GstQueue *queue);
 
 static GstElementStateReturn   gst_queue_change_state          (GstElement *element);
 
@@ -275,15 +274,6 @@ gst_queue_locked_flush (GstQueue *queue)
 }
 
 static void
-gst_queue_flush (GstQueue *queue)
-{
-  g_mutex_lock (queue->qlock);
-  gst_queue_locked_flush (queue);
-  g_mutex_unlock (queue->qlock);
-}
-
-
-static void
 gst_queue_chain (GstPad *pad, GstBuffer *buf)
 {
   GstQueue *queue;
@@ -378,7 +368,7 @@ restart:
          return;
        }
        else {
-          gst_element_info (GST_ELEMENT (queue), "waiting for the app to restart source pad elements");
+          g_print ("%s: waiting for the app to restart source pad elements\n", GST_ELEMENT_NAME (queue));
        }
       }
 
@@ -459,7 +449,7 @@ restart:
         goto restart;
       }
       else {
-        gst_element_info (GST_ELEMENT (queue), "waiting for the app to restart sink pad elements");
+        g_print ("%s: waiting for the app to restart source pad elements\n", GST_ELEMENT_NAME (queue));
       }
     }
 
index 9e7b7ff..977f2c2 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "gst_private.h"
 
+#include "gstsystemclock.h"
 #include "gstscheduler.h"
 
 static void    gst_scheduler_class_init        (GstSchedulerClass *klass);
@@ -67,6 +68,13 @@ gst_scheduler_class_init (GstSchedulerClass *klass)
 static void
 gst_scheduler_init (GstScheduler *sched)
 {
+  sched->clock_providers = NULL;
+  sched->clock_receivers = NULL;
+  sched->schedulers = NULL;
+  sched->state = GST_SCHEDULER_STATE_NONE;
+  sched->parent = NULL;
+  sched->parent_sched = NULL;
+  sched->clock = NULL;
 }
 
 /**
@@ -171,11 +179,48 @@ gst_scheduler_add_element (GstScheduler *sched, GstElement *element)
   g_return_if_fail (GST_IS_SCHEDULER (sched));
   g_return_if_fail (GST_IS_ELEMENT (element));
 
+  if (element->getclockfunc) {
+    sched->clock_providers = g_list_prepend (sched->clock_providers, element);
+  }
+  if (element->setclockfunc) {
+    sched->clock_receivers = g_list_prepend (sched->clock_receivers, element);
+  }
+
   if (CLASS (sched)->add_element)
     CLASS (sched)->add_element (sched, element);
 }
 
 /**
+ * gst_scheduler_remove_element:
+ * @sched: the schedulerr
+ * @element: the element to remov
+ *
+ * Remove an element from the schedulerr.
+ */
+void
+gst_scheduler_remove_element (GstScheduler *sched, GstElement *element)
+{
+  GList *pads;
+  
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+  g_return_if_fail (GST_IS_ELEMENT (element));
+
+  sched->clock_providers = g_list_remove (sched->clock_providers, element);
+  sched->clock_receivers = g_list_remove (sched->clock_receivers, element);
+
+  if (CLASS (sched)->remove_element)
+    CLASS (sched)->remove_element (sched, element);
+  
+  for (pads = element->pads; pads; pads = pads->next) {
+    GstPad *pad = GST_PAD (pads->data);
+    
+    if (GST_IS_REAL_PAD (pad)) {
+      gst_pad_unset_sched (GST_PAD (pads->data));
+    }
+  }
+}
+
+/**
  * gst_scheduler_state_transition:
  * @sched: the scheduler
  * @element: the element with the state transition
@@ -192,39 +237,66 @@ gst_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint t
   g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_STATE_FAILURE);
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
 
+  if (element == sched->parent && sched->parent_sched == NULL) {
+
+    switch (transition) {
+      case GST_STATE_READY_TO_PAUSED:
+      {
+        GstClock *clock = gst_scheduler_get_clock (sched);
+
+        if (clock)
+          gst_clock_reset (clock);
+
+       sched->current_clock = clock;
+        break;
+      }
+      case GST_STATE_PAUSED_TO_PLAYING:
+      {
+       gst_scheduler_set_clock (sched, sched->current_clock);
+        if (sched->current_clock)
+          gst_clock_activate (sched->current_clock, TRUE);
+        break;
+      }
+      case GST_STATE_PLAYING_TO_PAUSED:
+        if (sched->current_clock)
+          gst_clock_activate (sched->current_clock, FALSE);
+        break;
+    }
+  }
+
   if (CLASS (sched)->state_transition)
     return CLASS (sched)->state_transition (sched, element, transition);
 
   return GST_STATE_SUCCESS;
 }
 
-/**
- * gst_scheduler_remove_element:
- * @sched: the schedulerr
- * @element: the element to remov
- *
- * Remove an element from the schedulerr.
- */
 void
-gst_scheduler_remove_element (GstScheduler *sched, GstElement *element)
+gst_scheduler_add_scheduler (GstScheduler *sched, GstScheduler *sched2)
 {
-  GList *pads;
-  
   g_return_if_fail (GST_IS_SCHEDULER (sched));
-  g_return_if_fail (GST_IS_ELEMENT (element));
+  g_return_if_fail (GST_IS_SCHEDULER (sched2));
 
-  if (CLASS (sched)->remove_element)
-    CLASS (sched)->remove_element (sched, element);
-  
-  for (pads = element->pads; pads; pads = pads->next) {
-    GstPad *pad = GST_PAD (pads->data);
-    
-    if (GST_IS_REAL_PAD (pad)) {
-      gst_pad_unset_sched (GST_PAD (pads->data));
-    }
-  }
+  sched->schedulers = g_list_prepend (sched->schedulers, sched2);
+  sched2->parent_sched = sched;
+
+  if (CLASS (sched)->add_scheduler)
+    CLASS (sched)->add_scheduler (sched, sched2);
 }
 
+void
+gst_scheduler_remove_scheduler (GstScheduler *sched, GstScheduler *sched2)
+{
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+  g_return_if_fail (GST_IS_SCHEDULER (sched2));
+
+  sched->schedulers = g_list_remove (sched->schedulers, sched2);
+  sched2->parent_sched = NULL;
+
+  if (CLASS (sched)->remove_scheduler)
+    CLASS (sched)->remove_scheduler (sched, sched2);
+}
+
+
 /**
  * gst_scheduler_lock_element:
  * @sched: the scheduler
@@ -315,6 +387,106 @@ gst_scheduler_interrupt (GstScheduler *sched, GstElement *element)
   return FALSE;
 }
 
+GstClock*
+gst_scheduler_get_clock (GstScheduler *sched)
+{
+  GstClock *clock = NULL;
+  
+  if (GST_FLAG_IS_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK)) {
+    clock = sched->clock;  
+  }
+  else {
+    if (sched->schedulers) {
+      GList *schedulers = sched->schedulers;
+
+      while (schedulers) {
+        GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
+      
+        clock = gst_scheduler_get_clock (scheduler);
+        if (clock)
+         break;
+
+        schedulers = g_list_next (schedulers);
+      }
+    }
+    if (!clock && sched->clock_providers) {
+      clock = gst_element_get_clock (GST_ELEMENT (sched->clock_providers->data));
+    }
+    if (!clock && sched->parent_sched == NULL) {
+      clock = gst_system_clock_obtain ();
+    }
+  }
+
+  return clock;
+}
+
+void
+gst_scheduler_use_clock (GstScheduler *sched, GstClock *clock)
+{
+  g_return_if_fail (sched != NULL);
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+
+  GST_FLAG_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
+  sched->clock = clock;
+}
+
+void
+gst_scheduler_set_clock (GstScheduler *sched, GstClock *clock)
+{
+  GList *receivers;
+  GList *schedulers;
+
+  g_return_if_fail (sched != NULL);
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+
+  receivers = sched->clock_receivers;
+  schedulers = sched->schedulers;
+
+  sched->current_clock = clock;
+
+  while (receivers) {
+    GstElement *element = GST_ELEMENT (receivers->data);
+
+    gst_element_set_clock (element, clock);
+    receivers = g_list_next (receivers);
+  }
+  while (schedulers) {
+    GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
+
+    gst_scheduler_set_clock (scheduler, clock);
+    schedulers = g_list_next (schedulers);
+  }
+}
+
+void
+gst_scheduler_auto_clock (GstScheduler *sched)
+{
+  g_return_if_fail (sched != NULL);
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+
+  GST_FLAG_UNSET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
+  sched->clock = NULL;
+}
+
+/**
+ * gst_scheduler_clock_wait:
+ * @sched: the scheduler
+ *
+ * Perform one iteration on the schedulerr.
+ *
+ * Returns: a boolean indicating something usefull has happened.
+ */
+GstClockReturn
+gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time)
+{
+  g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
+
+  if (CLASS (sched)->clock_wait)
+    return CLASS (sched)->clock_wait (sched, element, clock, time);
+
+  return GST_CLOCK_TIMEOUT;
+}
+
 /**
  * gst_scheduler_iterate:
  * @sched: the scheduler
index 60e38e5..599172d 100644 (file)
@@ -44,6 +44,13 @@ extern "C" {
 #define GST_IS_SCHEDULER_CLASS(obj) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHEDULER))
 
+typedef enum {
+  /* this scheduler works with a fixed clock */
+  GST_SCHEDULER_FLAG_FIXED_CLOCK       = GST_OBJECT_FLAG_LAST,
+
+  /* padding */
+  GST_SCHEDULER_FLAG_LAST              = GST_OBJECT_FLAG_LAST + 4,
+} GstSchedulerFlags;
 
 #define GST_SCHEDULER_PARENT(sched)            ((sched)->parent)
 #define GST_SCHEDULER_STATE(sched)             ((sched)->state)
@@ -58,11 +65,19 @@ typedef enum {
 } GstSchedulerState;
 
 struct _GstScheduler {
-  GstObject object;
+  GstObject             object;
+
+  GstElement           *parent;
+  GstScheduler                 *parent_sched;
 
-  GstElement *parent;
+  GstSchedulerState     state;
+  GstClock             *clock;
+  GstClock             *current_clock;
 
-  GstSchedulerState state;
+  GList                        *clock_providers;
+  GList                        *clock_receivers;
+
+  GList                        *schedulers;
 };
 
 struct _GstSchedulerClass {
@@ -73,6 +88,8 @@ struct _GstSchedulerClass {
   void                         (*reset)                (GstScheduler *sched);
   void                         (*add_element)          (GstScheduler *sched, GstElement *element);
   void                         (*remove_element)       (GstScheduler *sched, GstElement *element);
+  void                         (*add_scheduler)        (GstScheduler *sched, GstScheduler *sched2);
+  void                         (*remove_scheduler)     (GstScheduler *sched, GstScheduler *sched2);
   GstElementStateReturn (*state_transition)    (GstScheduler *sched, GstElement *element, gint transition);
   void                         (*lock_element)         (GstScheduler *sched, GstElement *element);
   void                         (*unlock_element)       (GstScheduler *sched, GstElement *element);
@@ -82,6 +99,8 @@ struct _GstSchedulerClass {
   void                         (*pad_connect)          (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
   void                         (*pad_disconnect)       (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
   void                         (*pad_select)           (GstScheduler *sched, GList *padlist);
+  GstClockReturn       (*clock_wait)           (GstScheduler *sched, GstElement *element,
+                                                GstClock *clock, GstClockTime time);
   GstSchedulerState    (*iterate)              (GstScheduler *sched);
   /* for debugging */
   void                         (*show)                 (GstScheduler *sched);
@@ -98,6 +117,8 @@ void                 gst_scheduler_setup             (GstScheduler *sched);
 void                   gst_scheduler_reset             (GstScheduler *sched);
 void                   gst_scheduler_add_element       (GstScheduler *sched, GstElement *element);
 void                   gst_scheduler_remove_element    (GstScheduler *sched, GstElement *element);
+void                   gst_scheduler_add_scheduler     (GstScheduler *sched, GstScheduler *sched2);
+void                   gst_scheduler_remove_scheduler  (GstScheduler *sched, GstScheduler *sched2);
 GstElementStateReturn  gst_scheduler_state_transition  (GstScheduler *sched, GstElement *element, gint transition);
 void                   gst_scheduler_lock_element      (GstScheduler *sched, GstElement *element);
 void                   gst_scheduler_unlock_element    (GstScheduler *sched, GstElement *element);
@@ -107,8 +128,17 @@ void                       gst_scheduler_error             (GstScheduler *sched, GstElement *element);
 void                   gst_scheduler_pad_connect       (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 void                   gst_scheduler_pad_disconnect    (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 GstPad*                 gst_scheduler_pad_select       (GstScheduler *sched, GList *padlist);
+GstClock*              gst_scheduler_get_clock         (GstScheduler *sched);
+GstClock*              gst_scheduler_get_clock         (GstScheduler *sched);
+GstClockReturn         gst_scheduler_clock_wait        (GstScheduler *sched, GstElement *element,
+                                                        GstClock *clock, GstClockTime time);
 gboolean               gst_scheduler_iterate           (GstScheduler *sched);
 
+void                   gst_scheduler_use_clock         (GstScheduler *sched, GstClock *clock);
+void                   gst_scheduler_set_clock         (GstScheduler *sched, GstClock *clock);
+GstClock*              gst_scheduler_get_clock         (GstScheduler *sched);
+void                   gst_scheduler_auto_clock        (GstScheduler *sched);
+
 void                   gst_scheduler_show              (GstScheduler *sched);
 
 /*
index 7693c4f..cc82428 100644 (file)
@@ -34,11 +34,7 @@ static GstClock *_the_system_clock = NULL;
 static void            gst_system_clock_class_init     (GstSystemClockClass *klass);
 static void            gst_system_clock_init           (GstSystemClock *clock);
 
-static void            gst_system_clock_activate       (GstClock *clock, gboolean active);
-static void            gst_system_clock_reset          (GstClock *clock);
-static void            gst_system_clock_set_time       (GstClock *clock, GstClockTime time);
-static GstClockTime    gst_system_clock_get_time       (GstClock *clock);
-static GstClockReturn  gst_system_clock_wait           (GstClock *clock, GstClockTime time);
+static GstClockTime    gst_system_clock_get_internal_time      (GstClock *clock);
 static guint64         gst_system_clock_get_resolution (GstClock *clock);
 
 
@@ -82,11 +78,7 @@ gst_system_clock_class_init (GstSystemClockClass *klass)
 
   parent_class = g_type_class_ref (GST_TYPE_CLOCK);
 
-  gstclock_class->activate =           gst_system_clock_activate;
-  gstclock_class->reset =              gst_system_clock_reset;
-  gstclock_class->set_time =           gst_system_clock_set_time;
-  gstclock_class->get_time =           gst_system_clock_get_time;
-  gstclock_class->wait =               gst_system_clock_wait;
+  gstclock_class->get_internal_time =  gst_system_clock_get_internal_time;
   gstclock_class->get_resolution =     gst_system_clock_get_resolution;
 }
 
@@ -105,89 +97,12 @@ gst_system_clock_obtain (void)
   return _the_system_clock;
 }
 
-static void
-gst_system_clock_activate (GstClock *clock, gboolean active)
-{
-  GTimeVal timeval;
-  GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
-
-  g_get_current_time (&timeval);
-  GST_LOCK (clock);
-  if (active) {
-    sys_clock->absolute_start = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->current_time;;
-  }
-  else {
-    sys_clock->current_time = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->absolute_start;
-  }
-  GST_UNLOCK (clock);
-}
-
-static void
-gst_system_clock_set_time (GstClock *clock, GstClockTime time)
-{
-  GTimeVal timeval;
-  GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
-
-  g_get_current_time (&timeval);
-
-  GST_LOCK (clock);
-  sys_clock->absolute_start = GST_TIMEVAL_TO_TIME (timeval) - time;
-  sys_clock->current_time = time;
-  GST_UNLOCK (clock);
-}
-
-static void
-gst_system_clock_reset (GstClock *clock)
-{
-  gst_system_clock_set_time (clock, 0LL);
-}
-
 static GstClockTime
-gst_system_clock_get_time (GstClock *clock)
-{
-  GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
-  GstClockTime res;
-
-  if (!clock->active) {
-    GST_LOCK (clock);
-    res = sys_clock->current_time;
-  }
-  else {
-    GTimeVal timeval;
-
-    g_get_current_time (&timeval);
-
-    GST_LOCK (clock);
-    res = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->absolute_start;
-  }
-  GST_UNLOCK (clock);
-
-  return res;
-}
-
-static GstClockReturn
-gst_system_clock_wait (GstClock *clock, GstClockTime time)
+gst_system_clock_get_internal_time (GstClock *clock)
 {
-  GstClockTime target;
   GTimeVal timeval;
-  GCond *cond = g_cond_new ();
-  GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
-  GstClockReturn ret;
-
-  GST_LOCK (clock);
-  target = time + sys_clock->absolute_start;
-       
-  timeval.tv_usec = target % 1000000;
-  timeval.tv_sec = target / 1000000;
-
-  g_cond_timed_wait (cond, GST_GET_LOCK (clock), &timeval); 
-  GST_UNLOCK (clock);
-
-  ret = GST_CLOCK_TIMEOUT;
-
-  g_cond_free (cond);
-
-  return ret;
+  g_get_current_time (&timeval);
+  return GST_TIMEVAL_TO_TIME (timeval);
 }
 
 static guint64
index 16c11b3..f972e12 100644 (file)
@@ -47,9 +47,6 @@ typedef struct _GstSystemClockClass GstSystemClockClass;
 
 struct _GstSystemClock {
   GstClock clock;
-
-  GstClockTime absolute_start;
-  GstClockTime current_time;
 };
 
 struct _GstSystemClockClass {
index 94e8a61..e6044e1 100644 (file)
@@ -140,6 +140,7 @@ gst_thread_init (GstThread *thread)
 
   /* we're a manager by default */
   GST_FLAG_SET (thread, GST_BIN_FLAG_MANAGER);
+  GST_FLAG_SET (thread, GST_BIN_SELF_SCHEDULABLE);
 
   schedname = gst_schedulerfactory_get_default_name ();
 
index 6ee1cbf..d8cc400 100644 (file)
@@ -199,28 +199,6 @@ gst_util_get_pointer_arg (GObject * object, const gchar * argname)
 }
 
 /**
- * gst_util_get_widget_property:
- * @object: the object to query
- * @argname: the name of the argument
- *
- * Retrieves a property of an object as a widget.
- *
- * Returns: the property of the object
- */
-/* COMMENTED OUT BECAUSE WE HAVE NO MORE gtk.h
-GtkWidget*
-gst_util_get_widget_property (GObject *object, const gchar *argname) 
-{
-  GtkArg arg;
-
-  arg.name = argname;
-  gtk_object_getv(G_OBJECT(object),1,&arg);
-  
-  return GTK_WIDGET(G_VALUE_OBJECT(arg));
-}
-*/
-
-/**
  * gst_util_dump_mem:
  * @mem: a pointer to the memory to dump
  * @size: the size of the memory block to dump
@@ -448,7 +426,6 @@ gst_util_set_object_arg (GObject * object, const gchar * name, const gchar * val
 #include "gstpad.h"
 #include "gsttype.h"
 #include "gstprops.h"
-#include "gstpropsprivate.h"
 
 static void
 string_append_indent (GString * str, gint count)
@@ -460,15 +437,16 @@ string_append_indent (GString * str, gint count)
 }
 
 static void
-gst_print_props (GString * buf, gint indent, GList * props, gboolean showname)
+gst_print_props (GString *buf, gint indent, GList *props, gboolean showname)
 {
   GList *elem;
   guint width = 0;
+  GstPropsType type;
 
   if (showname)
     for (elem = props; elem; elem = g_list_next (elem)) {
       GstPropsEntry *prop = elem->data;
-      const gchar *name = g_quark_to_string (prop->propid);
+      const gchar *name = gst_props_entry_get_name (prop);
 
       if (width < strlen (name))
        width = strlen (name);
@@ -479,45 +457,76 @@ gst_print_props (GString * buf, gint indent, GList * props, gboolean showname)
 
     string_append_indent (buf, indent);
     if (showname) {
-      const gchar *name = g_quark_to_string (prop->propid);
+      const gchar *name = gst_props_entry_get_name (prop);
 
       g_string_append (buf, name);
       string_append_indent (buf, 2 + width - strlen (name));
     }
 
-    switch (prop->propstype) {
-      case GST_PROPS_INT_ID:
-       g_string_append_printf (buf, "%d (int)\n", prop->data.int_data);
+    type = gst_props_entry_get_type (prop);
+    switch (type) {
+      case GST_PROPS_INT_TYPE:
+      {
+       gint val;
+       gst_props_entry_get_int (prop, &val);
+       g_string_append_printf (buf, "%d (int)\n", val);
        break;
-      case GST_PROPS_INT_RANGE_ID:
-       g_string_append_printf (buf, "%d - %d (int)\n",
-                               prop->data.int_range_data.min, prop->data.int_range_data.max);
+      }
+      case GST_PROPS_INT_RANGE_TYPE:
+      {
+       gint min, max;
+       gst_props_entry_get_int_range (prop, &min, &max);
+       g_string_append_printf (buf, "%d - %d (int)\n", min, max);
        break;
-      case GST_PROPS_FLOAT_ID:
-       g_string_append_printf (buf, "%f (float)\n", prop->data.float_data);
+      }
+      case GST_PROPS_FLOAT_TYPE:
+      {
+       gfloat val;
+       gst_props_entry_get_float (prop, &val);
+       g_string_append_printf (buf, "%f (float)\n", val);
        break;
-      case GST_PROPS_FLOAT_RANGE_ID:
-       g_string_append_printf (buf, "%f - %f (float)\n",
-                               prop->data.float_range_data.min, prop->data.float_range_data.max);
+      }
+      case GST_PROPS_FLOAT_RANGE_TYPE:
+      {
+       gfloat min, max;
+       gst_props_entry_get_float_range (prop, &min, &max);
+       g_string_append_printf (buf, "%f - %f (float)\n", min, max);
        break;
-      case GST_PROPS_BOOL_ID:
-       g_string_append_printf (buf, "%s\n", prop->data.bool_data ? "TRUE" : "FALSE");
+      }
+      case GST_PROPS_BOOL_TYPE:
+      {
+       gboolean val;
+       gst_props_entry_get_boolean (prop, &val);
+       g_string_append_printf (buf, "%s\n", val ? "TRUE" : "FALSE");
        break;
-      case GST_PROPS_STRING_ID:
-       g_string_append_printf (buf, "\"%s\"\n", prop->data.string_data.string);
+      }
+      case GST_PROPS_STRING_TYPE:
+      {
+       const gchar *val;
+       gst_props_entry_get_string (prop, &val);
+       g_string_append_printf (buf, "\"%s\"\n", val);
        break;
-      case GST_PROPS_FOURCC_ID:
+      }
+      case GST_PROPS_FOURCC_TYPE:
+      {
+       guint32 val;
+       gst_props_entry_get_fourcc_int (prop, &val);
        g_string_append_printf (buf, "'%c%c%c%c' (fourcc)\n",
-                               prop->data.fourcc_data & 0xff,
-                               prop->data.fourcc_data >> 8 & 0xff,
-                               prop->data.fourcc_data >> 16 & 0xff,
-                               prop->data.fourcc_data >> 24 & 0xff);
+                               (gchar)( val        & 0xff),
+                               (gchar)((val >> 8)  & 0xff),
+                               (gchar)((val >> 16) & 0xff),
+                               (gchar)((val >> 24) & 0xff));
        break;
-      case GST_PROPS_LIST_ID:
-       gst_print_props (buf, indent + 2, prop->data.list_data.entries, FALSE);
+      }
+      case GST_PROPS_LIST_TYPE:
+      {
+       const GList *list;
+       gst_props_entry_get_list (prop, &list);
+       gst_print_props (buf, indent + 2, (GList *)list, FALSE);
        break;
+      }
       default:
-       g_string_append_printf (buf, "unknown proptype %d\n", prop->propstype);
+       g_string_append_printf (buf, "unknown proptype %d\n", type);
        break;
     }
   }
index 9124cfe..4b8a46c 100644 (file)
@@ -41,8 +41,7 @@ gfloat                gst_util_get_float_arg          (GObject *object, const gchar *argname);
 gdouble        gst_util_get_double_arg         (GObject *object, const gchar *argname);
 const gchar*   gst_util_get_string_arg         (GObject *object, const gchar *argname);
 gpointer       gst_util_get_pointer_arg        (GObject *object, const gchar *argname);
-/*GtkWidget*   gst_util_get_widget_property    (GObject *object, const gchar *argname);*/
-void           gst_util_set_value_from_string(GValue *value, const gchar *value_str);
+void           gst_util_set_value_from_string  (GValue *value, const gchar *value_str);
 void           gst_util_set_object_arg         (GObject *object, const gchar *name, const gchar *value);
        
 void           gst_util_dump_mem               (guchar *mem, guint size);
index f7abe84..8038929 100644 (file)
@@ -1,6 +1,6 @@
 plugindir = $(libdir)/gst
 
-plugin_LTLIBRARIES = libgstbasicscheduler.la libgststandardscheduler.la
+plugin_LTLIBRARIES = libgstbasicscheduler.la libgststandardscheduler.la libgstfastscheduler.la
 
 libgstbasicscheduler_la_SOURCES = gstbasicscheduler.c 
 libgstbasicscheduler_la_CFLAGS = $(GST_CFLAGS)
@@ -12,6 +12,11 @@ libgststandardscheduler_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/libs/ext/cothr
 libgststandardscheduler_la_LIBADD = $(top_builddir)/libs/ext/cothreads/cothreads/libcothreads-gthreads.la
 libgststandardscheduler_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
+libgstfastscheduler_la_SOURCES = gstfastscheduler.c 
+libgstfastscheduler_la_CFLAGS = $(GST_CFLAGS)
+libgstfastscheduler_la_LIBADD = $(GST_LIBS) ../libcothreads.la
+libgstfastscheduler_la_LDFLAGS = @GST_LT_LDFLAGS@
+
 ## this is a REALLY evil hack 
 ## but we need to keep it as long as we have libs/gst and libs/ext
 $(top_builddir)/libs/ext/cothreads/cothreads/libcothreads-gthreads.la:
index 169ac06..4176728 100644 (file)
@@ -72,7 +72,7 @@ typedef enum {
 
 typedef enum {
   /* something important has changed inside the scheduler */
-  GST_BASIC_SCHEDULER_CHANGE   = GST_OBJECT_FLAG_LAST,
+  GST_BASIC_SCHEDULER_CHANGE   = GST_SCHEDULER_FLAG_LAST,
 } GstBasicSchedulerFlags;
 
 struct _GstBasicScheduler {
@@ -112,6 +112,8 @@ static void                 gst_basic_scheduler_error               (GstScheduler *sched, GstElement *elem
 static void            gst_basic_scheduler_pad_connect         (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 static void            gst_basic_scheduler_pad_disconnect      (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 static GstPad*         gst_basic_scheduler_pad_select          (GstScheduler *sched, GList *padlist);
+static GstClockReturn  gst_basic_scheduler_clock_wait          (GstScheduler *sched, GstElement *element,
+                                                                GstClock *clock, GstClockTime time);
 static GstSchedulerState
                        gst_basic_scheduler_iterate             (GstScheduler *sched);
 
@@ -169,6 +171,7 @@ gst_basic_scheduler_class_init (GstBasicSchedulerClass * klass)
   gstscheduler_class->pad_connect      = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pad_connect);
   gstscheduler_class->pad_disconnect   = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pad_disconnect);
   gstscheduler_class->pad_select       = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pad_select);
+  gstscheduler_class->clock_wait       = GST_DEBUG_FUNCPTR (gst_basic_scheduler_clock_wait);
   gstscheduler_class->iterate          = GST_DEBUG_FUNCPTR (gst_basic_scheduler_iterate);
 
   gstscheduler_class->show             = GST_DEBUG_FUNCPTR (gst_basic_scheduler_show);
@@ -424,6 +427,9 @@ gst_basic_scheduler_gethandler_proxy (GstPad * pad)
     if (GST_RPAD_PEER (peer) != (GstRealPad *) pad) {
       GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!");
       pad = (GstPad *) GST_RPAD_PEER (peer);
+      if (!pad) {
+       gst_element_error (GST_ELEMENT (GST_PAD_PARENT (peer)), "pad unconnected");
+      }
     }
   }
   GST_DEBUG (GST_CAT_DATAFLOW, "done switching");
@@ -530,7 +536,7 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
       if (!GST_IS_REAL_PAD (pad))
        continue;
       
-      peerpad = GST_PAD (GST_RPAD_PEER (pad));
+      peerpad = GST_PAD_PEER (pad);
 
       /* if the element is DECOUPLED or outside the manager, we have to chain */
       if ((wrapper_function == NULL) ||
@@ -677,6 +683,7 @@ gst_basic_scheduler_chain_enable_element (GstSchedulerChain * chain, GstElement
 
   /* notify the scheduler that something changed */
   GST_FLAG_SET(chain->sched, GST_BASIC_SCHEDULER_CHANGE);
+  //GST_FLAG_UNSET(element, GST_ELEMENT_COTHREAD_STOPPING);
 
   /* reschedule the chain */
   return gst_basic_scheduler_cothreaded_chain (GST_BIN (GST_SCHEDULER (chain->sched)->parent), chain);
@@ -696,6 +703,7 @@ gst_basic_scheduler_chain_disable_element (GstSchedulerChain * chain, GstElement
 
   /* notify the scheduler that something changed */
   GST_FLAG_SET(chain->sched, GST_BASIC_SCHEDULER_CHANGE);
+  GST_FLAG_SET(element, GST_ELEMENT_COTHREAD_STOPPING);
 
   /* reschedule the chain */
 /* FIXME this should be done only if manager state != NULL */
@@ -969,19 +977,6 @@ gst_basic_scheduler_remove_element (GstScheduler * sched, GstElement * element)
     /* find what chain the element is in */
     chain = gst_basic_scheduler_find_chain (bsched, element);
 
-    if (GST_ELEMENT_IS_COTHREAD_STOPPING (element)) {
-      GstElement *entry = GST_ELEMENT (cothread_get_private (cothread_current ()));
-
-      if (entry == element) {
-        g_warning ("removing currently running element! %s", GST_ELEMENT_NAME (entry));
-      }
-      else if (entry) {
-        GST_INFO (GST_CAT_SCHEDULING, "moving stopping to element \"%s\"",
-             GST_ELEMENT_NAME (entry));
-       GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING);
-      }
-    }
-    
     /* remove it from its chain */
     gst_basic_scheduler_chain_remove_element (chain, element);
 
@@ -1196,6 +1191,13 @@ gst_basic_scheduler_pad_select (GstScheduler * sched, GList * padlist)
   return pad;
 }
 
+static GstClockReturn
+gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
+                               GstClock *clock, GstClockTime time)
+{
+  return gst_clock_wait (clock, time);
+}
+
 static GstSchedulerState
 gst_basic_scheduler_iterate (GstScheduler * sched)
 {
diff --git a/gst/schedulers/gstfastscheduler.c b/gst/schedulers/gstfastscheduler.c
new file mode 100644 (file)
index 0000000..45a1264
--- /dev/null
@@ -0,0 +1,1095 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstscheduler.c: Default scheduling code for most cases
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*#define GST_DEBUG_ENABLED */
+#include <gst/gst.h>
+#include <../cothreads.h>
+
+typedef struct _GstSchedulerChain GstSchedulerChain;
+
+#define GST_PAD_THREADSTATE(pad)               (cothread_state*) (GST_PAD_CAST (pad)->sched_private)
+#define GST_ELEMENT_THREADSTATE(elem)          (cothread_state*) (GST_ELEMENT_CAST (elem)->sched_private)
+#define GST_BIN_THREADCONTEXT(bin)             (cothread_context*) (GST_BIN_CAST (bin)->sched_private)
+
+#define GST_ELEMENT_COTHREAD_STOPPING                  GST_ELEMENT_SCHEDULER_PRIVATE1
+#define GST_ELEMENT_IS_COTHREAD_STOPPING(element)      GST_FLAG_IS_SET((element), GST_ELEMENT_COTHREAD_STOPPING)
+#define GST_ELEMENT_INTERRUPTED                                GST_ELEMENT_SCHEDULER_PRIVATE2
+#define GST_ELEMENT_IS_INTERRUPTED(element)            GST_FLAG_IS_SET((element), GST_ELEMENT_INTERRUPTED)
+
+typedef struct _GstFastScheduler GstFastScheduler;
+typedef struct _GstFastSchedulerClass GstFastSchedulerClass;
+
+struct _GstSchedulerChain {
+  GstFastScheduler *sched;
+
+  GList *disabled;
+
+  GList *elements;
+  gint num_elements;
+
+  GstElement *entry;
+
+  GList *cothreaded_elements;
+  gint num_cothreaded;
+
+  gboolean schedule;
+};
+
+#define GST_TYPE_FAST_SCHEDULER \
+  (gst_fast_scheduler_get_type())
+#define GST_FAST_SCHEDULER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FAST_SCHEDULER,GstFastScheduler))
+#define GST_FAST_SCHEDULER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FAST_SCHEDULER,GstFastSchedulerClass))
+#define GST_IS_FAST_SCHEDULER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAST_SCHEDULER))
+#define GST_IS_FAST_SCHEDULER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAST_SCHEDULER))
+
+#define GST_FAST_SCHEDULER_CAST(sched) ((GstFastScheduler *)(sched))
+
+typedef enum {
+  GST_FAST_SCHEDULER_STATE_NONE,
+  GST_FAST_SCHEDULER_STATE_STOPPED,
+  GST_FAST_SCHEDULER_STATE_ERROR,
+  GST_FAST_SCHEDULER_STATE_RUNNING,
+} GstFastSchedulerState;
+
+struct _GstFastScheduler {
+  GstScheduler parent;
+
+  GList *elements;
+  gint num_elements;
+
+  GList *chains;
+  gint num_chains;
+
+  GstFastSchedulerState state;
+
+};
+
+struct _GstFastSchedulerClass {
+  GstSchedulerClass parent_class;
+};
+
+static GType _gst_fast_scheduler_type = 0;
+
+static void            gst_fast_scheduler_class_init           (GstFastSchedulerClass * klass);
+static void            gst_fast_scheduler_init                 (GstFastScheduler * scheduler);
+
+static void            gst_fast_scheduler_dispose              (GObject *object);
+
+static void            gst_fast_scheduler_setup                (GstScheduler *sched);
+static void            gst_fast_scheduler_reset                (GstScheduler *sched);
+static void            gst_fast_scheduler_add_element          (GstScheduler *sched, GstElement *element);
+static void            gst_fast_scheduler_remove_element       (GstScheduler *sched, GstElement *element);
+static GstElementStateReturn  
+                       gst_fast_scheduler_state_transition     (GstScheduler *sched, GstElement *element, gint transition);
+static void            gst_fast_scheduler_lock_element         (GstScheduler *sched, GstElement *element);
+static void            gst_fast_scheduler_unlock_element       (GstScheduler *sched, GstElement *element);
+static void            gst_fast_scheduler_yield                (GstScheduler *sched, GstElement *element);
+static gboolean                gst_fast_scheduler_interrupt            (GstScheduler *sched, GstElement *element);
+static void            gst_fast_scheduler_error                (GstScheduler *sched, GstElement *element);
+static void            gst_fast_scheduler_pad_connect          (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
+static void            gst_fast_scheduler_pad_disconnect       (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
+static GstPad*         gst_fast_scheduler_pad_select           (GstScheduler *sched, GList *padlist);
+static GstSchedulerState
+                       gst_fast_scheduler_iterate              (GstScheduler *sched);
+
+static void            gst_fast_scheduler_show                 (GstScheduler *sched);
+
+static GstSchedulerClass *parent_class = NULL;
+
+static GType
+gst_fast_scheduler_get_type (void)
+{
+  if (!_gst_fast_scheduler_type) {
+    static const GTypeInfo scheduler_info = {
+      sizeof (GstFastSchedulerClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_fast_scheduler_class_init,
+      NULL,
+      NULL,
+      sizeof (GstFastScheduler),
+      0,
+      (GInstanceInitFunc) gst_fast_scheduler_init,
+      NULL
+    };
+
+    _gst_fast_scheduler_type = g_type_register_static (GST_TYPE_SCHEDULER, "GstFastScheduler", &scheduler_info, 0);
+  }
+  return _gst_fast_scheduler_type;
+}
+
+static void
+gst_fast_scheduler_class_init (GstFastSchedulerClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstObjectClass *gstobject_class;
+  GstSchedulerClass *gstscheduler_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstobject_class = (GstObjectClass*)klass;
+  gstscheduler_class = (GstSchedulerClass*)klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_SCHEDULER);
+
+  gobject_class->dispose       = GST_DEBUG_FUNCPTR (gst_fast_scheduler_dispose);
+
+  gstscheduler_class->setup            = GST_DEBUG_FUNCPTR (gst_fast_scheduler_setup);
+  gstscheduler_class->reset            = GST_DEBUG_FUNCPTR (gst_fast_scheduler_reset);
+  gstscheduler_class->add_element      = GST_DEBUG_FUNCPTR (gst_fast_scheduler_add_element);
+  gstscheduler_class->remove_element   = GST_DEBUG_FUNCPTR (gst_fast_scheduler_remove_element);
+  gstscheduler_class->state_transition         = GST_DEBUG_FUNCPTR (gst_fast_scheduler_state_transition);
+  gstscheduler_class->lock_element     = GST_DEBUG_FUNCPTR (gst_fast_scheduler_lock_element);
+  gstscheduler_class->unlock_element   = GST_DEBUG_FUNCPTR (gst_fast_scheduler_unlock_element);
+  gstscheduler_class->yield            = GST_DEBUG_FUNCPTR (gst_fast_scheduler_yield);
+  gstscheduler_class->interrupt        = GST_DEBUG_FUNCPTR (gst_fast_scheduler_interrupt);
+  gstscheduler_class->error            = GST_DEBUG_FUNCPTR (gst_fast_scheduler_error);
+  gstscheduler_class->pad_connect      = GST_DEBUG_FUNCPTR (gst_fast_scheduler_pad_connect);
+  gstscheduler_class->pad_disconnect   = GST_DEBUG_FUNCPTR (gst_fast_scheduler_pad_disconnect);
+  gstscheduler_class->pad_select       = GST_DEBUG_FUNCPTR (gst_fast_scheduler_pad_select);
+  gstscheduler_class->iterate          = GST_DEBUG_FUNCPTR (gst_fast_scheduler_iterate);
+}
+
+static void
+gst_fast_scheduler_init (GstFastScheduler *scheduler)
+{
+  scheduler->elements = NULL;
+  scheduler->num_elements = 0;
+  scheduler->chains = NULL;
+  scheduler->num_chains = 0;
+}
+
+static void
+gst_fast_scheduler_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstSchedulerFactory *factory;
+
+  gst_plugin_set_longname (plugin, "A fast scheduler");
+
+  factory = gst_schedulerfactory_new ("fast",
+                                     "A fast scheduler, it uses cothreads",
+                                     gst_fast_scheduler_get_type());
+
+  if (factory != NULL) {
+    gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+  }
+  else {
+    g_warning ("could not register scheduler: fast");
+  }
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "gstfastscheduler",
+  plugin_init
+};
+
+static int
+gst_fast_scheduler_loopfunc_wrapper (int argc, char *argv[])
+{
+  GstElement *element = GST_ELEMENT_CAST (argv);
+  G_GNUC_UNUSED const gchar *name = GST_ELEMENT_NAME (element);
+
+  GST_DEBUG_ENTER ("(%d,'%s')", argc, name);
+
+  do {
+    GST_DEBUG (GST_CAT_DATAFLOW, "calling loopfunc %s for element %s\n",
+              GST_DEBUG_FUNCPTR_NAME (element->loopfunc), name);
+    (element->loopfunc) (element);
+    GST_DEBUG (GST_CAT_DATAFLOW, "element %s ended loop function\n", name);
+
+  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+  GST_FLAG_UNSET (element, GST_ELEMENT_COTHREAD_STOPPING);
+
+  GST_DEBUG_LEAVE ("(%d,'%s')", argc, name);
+  return 0;
+}
+
+static void 
+gst_fast_scheduler_chainfunc_proxy (GstPad *pad, GstBuffer *buffer)
+{
+  GstElement *element = GST_PAD_PARENT (pad);
+
+  GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
+
+  GST_RPAD_BUFPEN (pad) = buffer;
+
+  while (GST_RPAD_BUFPEN (pad) != NULL) {
+    if (GST_ELEMENT_THREADSTATE (element)) {
+      cothread_switch (GST_ELEMENT_THREADSTATE (element));
+    }
+    else {
+      g_assert_not_reached();
+    }
+  }
+  GST_DEBUG_LEAVE ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
+}
+
+static GstBuffer* 
+gst_fast_scheduler_getfunc_proxy (GstPad *pad)
+{
+  GstElement *element = GST_PAD_PARENT (pad);
+  GstPad *peer = GST_PAD_CAST (GST_RPAD_PEER (pad));
+  GstBuffer *buf;
+
+  GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
+
+  while (GST_RPAD_BUFPEN (peer) == NULL) {
+    if (GST_ELEMENT_THREADSTATE (element)) {
+      cothread_switch (GST_ELEMENT_THREADSTATE (element));
+    }
+    else {
+      g_assert_not_reached();
+    }
+  }
+
+  GST_DEBUG_LEAVE ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
+  buf = GST_RPAD_BUFPEN (peer);
+  GST_RPAD_BUFPEN (peer) = NULL;
+
+  return buf;
+}
+
+static gboolean
+gst_fast_scheduler_cothreaded_element (GstBin * bin, GstElement *element)
+{
+  GList *elements;
+  cothread_func wrapper_function;
+  GList *pads;
+
+  GST_DEBUG (GST_CAT_SCHEDULING, "element is using COTHREADS\n");
+
+  g_assert (GST_BIN_THREADCONTEXT (bin) != NULL);
+
+  wrapper_function = GST_DEBUG_FUNCPTR (gst_fast_scheduler_loopfunc_wrapper);
+
+  if (GST_ELEMENT_THREADSTATE (element) == NULL) {
+    GST_ELEMENT_THREADSTATE (element) = cothread_create (GST_BIN_THREADCONTEXT (bin));
+    if (GST_ELEMENT_THREADSTATE (element) == NULL) {
+      gst_element_error (element, "could not create cothread for \"%s\"", 
+                         GST_ELEMENT_NAME (element), NULL);
+      return FALSE;
+    }
+    GST_DEBUG (GST_CAT_SCHEDULING, "created cothread %p for '%s'\n", 
+                  GST_ELEMENT_THREADSTATE (element),
+                  GST_ELEMENT_NAME (element));
+    cothread_setfunc (GST_ELEMENT_THREADSTATE (element), wrapper_function, 0, (char **) element);
+    GST_DEBUG (GST_CAT_SCHEDULING, "set wrapper function for '%s' to &%s\n",
+                GST_ELEMENT_NAME (element), GST_DEBUG_FUNCPTR_NAME (wrapper_function));
+  }
+
+  pads = gst_element_get_pad_list (element);
+
+  while (pads) {
+    GstPad *pad = GST_PAD_CAST (pads->data);
+    pads = g_list_next (pads);
+
+    if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
+      GST_DEBUG (GST_CAT_SCHEDULING, "setting gethandler to getfunc_proxy for %s:%s\n", GST_DEBUG_PAD_NAME (pad));
+      GST_RPAD_GETHANDLER (pad) = gst_fast_scheduler_getfunc_proxy;
+    }
+    else {
+      GST_DEBUG (GST_CAT_SCHEDULING, "setting chainhandler to chainfunc_proxy for %s:%s\n", GST_DEBUG_PAD_NAME (pad));
+      GST_RPAD_CHAINHANDLER (pad) = gst_fast_scheduler_chainfunc_proxy;
+    }
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_fast_scheduler_chained_element (GstBin *bin, GstElement *element) {
+  GList *pads;
+  GstPad *pad;
+
+  GST_DEBUG (GST_CAT_SCHEDULING,"chain entered\n");
+
+  // walk through all the pads
+  pads = gst_element_get_pad_list (element);
+  while (pads) {
+    pad = GST_PAD (pads->data);
+    pads = g_list_next (pads);
+    if (!GST_IS_REAL_PAD (pad)) 
+      continue;
+
+    if (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK) {
+      GST_DEBUG (GST_CAT_SCHEDULING,"copying chain function into chain handler for %s:%s\n",GST_DEBUG_PAD_NAME (pad));
+      GST_RPAD_CHAINHANDLER (pad) = GST_RPAD_CHAINFUNC (pad);
+    } else {
+      GST_DEBUG (GST_CAT_SCHEDULING,"copying get function into get handler for %s:%s\n",GST_DEBUG_PAD_NAME (pad));
+      if (!GST_RPAD_GETFUNC (pad)) 
+        GST_RPAD_GETHANDLER (pad) = gst_fast_scheduler_getfunc_proxy;
+      else 
+        GST_RPAD_GETHANDLER (pad) = GST_RPAD_GETFUNC (pad);
+    }
+  }
+
+  return TRUE;
+}
+
+
+static GstSchedulerChain *
+gst_fast_scheduler_chain_new (GstFastScheduler * sched)
+{
+  GstSchedulerChain *chain = g_new (GstSchedulerChain, 1);
+
+  /* initialize the chain with sane values */
+  chain->sched = sched;
+  chain->disabled = NULL;
+  chain->elements = NULL;
+  chain->num_elements = 0;
+  chain->entry = NULL;
+  chain->cothreaded_elements = NULL;
+  chain->num_cothreaded = 0;
+  chain->schedule = FALSE;
+
+  /* add the chain to the schedulers' list of chains */
+  sched->chains = g_list_prepend (sched->chains, chain);
+  sched->num_chains++;
+
+  GST_INFO (GST_CAT_SCHEDULING, "created new chain %p, now are %d chains in sched %p",
+           chain, sched->num_chains, sched);
+
+  return chain;
+}
+
+static void
+gst_fast_scheduler_chain_destroy (GstSchedulerChain * chain)
+{
+  GstFastScheduler *sched = chain->sched;
+
+
+  /* remove the chain from the schedulers' list of chains */
+  sched->chains = g_list_remove (sched->chains, chain);
+  sched->num_chains--;
+
+  /* destroy the chain */
+  g_list_free (chain->disabled);       /* should be empty... */
+  g_list_free (chain->elements);       /* ditto              */
+
+  GST_INFO (GST_CAT_SCHEDULING, "destroyed chain %p, now are %d chains in sched %p", chain,
+           sched->num_chains, sched);
+
+  g_free (chain);
+}
+
+static gboolean
+gst_fast_scheduler_chain_enable_element (GstSchedulerChain * chain, GstElement * element)
+{
+  GST_INFO (GST_CAT_SCHEDULING, "enabling element \"%s\" in chain %p, %d cothreaded elements", 
+                 GST_ELEMENT_NAME (element), chain, chain->num_cothreaded);
+
+  /* remove from disabled list */
+  chain->disabled = g_list_remove (chain->disabled, element);
+
+  /* add to elements list */
+  chain->elements = g_list_prepend (chain->elements, element);
+
+  /* reschedule the chain */
+  if (element->loopfunc) {
+    chain->cothreaded_elements = g_list_prepend (chain->cothreaded_elements, element);
+    chain->num_cothreaded++;
+
+    return gst_fast_scheduler_cothreaded_element (GST_BIN (GST_SCHEDULER (chain->sched)->parent), element);
+  }
+  else {
+    if (element->numsinkpads == 0 || GST_ELEMENT_IS_DECOUPLED (element)) {
+      chain->entry = element;
+    }
+
+    return gst_fast_scheduler_chained_element (GST_BIN (GST_SCHEDULER (chain->sched)->parent), element);
+  }
+}
+
+static void
+gst_fast_scheduler_chain_disable_element (GstSchedulerChain * chain, GstElement * element)
+{
+  GST_INFO (GST_CAT_SCHEDULING, "disabling element \"%s\" in chain %p", GST_ELEMENT_NAME (element),
+           chain);
+
+  /* remove from elements list */
+  chain->elements = g_list_remove (chain->elements, element);
+
+  /* add to disabled list */
+  chain->disabled = g_list_prepend (chain->disabled, element);
+
+  if (element->loopfunc) {
+    chain->cothreaded_elements = g_list_remove (chain->cothreaded_elements, element);
+    chain->num_cothreaded--;
+  }
+  else {
+    if (chain->entry == element)
+      chain->entry = NULL;
+  }
+}
+
+static void
+gst_fast_scheduler_chain_add_element (GstSchedulerChain * chain, GstElement * element)
+{
+  GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to chain %p", GST_ELEMENT_NAME (element),
+           chain);
+
+  /* set the sched pointer for the element */
+  element->sched = GST_SCHEDULER (chain->sched);
+
+  /* add the element to the list of 'disabled' elements */
+  chain->disabled = g_list_prepend (chain->disabled, element);
+  chain->num_elements++;
+}
+
+static void
+gst_fast_scheduler_chain_remove_element (GstSchedulerChain * chain, GstElement * element)
+{
+  GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from chain %p", GST_ELEMENT_NAME (element),
+           chain);
+
+  /* if it's active, deactivate it */
+  if (g_list_find (chain->elements, element)) {
+    gst_fast_scheduler_chain_disable_element (chain, element);
+  }
+  /* we have to check for a threadstate here because a queue doesn't have one */
+  if (GST_ELEMENT_THREADSTATE (element)) {
+    cothread_free (GST_ELEMENT_THREADSTATE (element));
+    GST_ELEMENT_THREADSTATE (element) = NULL;
+  }
+
+  /* remove the element from the list of elements */
+  chain->disabled = g_list_remove (chain->disabled, element);
+  chain->num_elements--;
+
+  /* if there are no more elements in the chain, destroy the chain */
+  if (chain->num_elements == 0)
+    gst_fast_scheduler_chain_destroy (chain);
+}
+
+static void
+gst_fast_scheduler_chain_elements (GstFastScheduler * sched, GstElement * element1, GstElement * element2)
+{
+  GList *chains;
+  GstSchedulerChain *chain;
+  GstSchedulerChain *chain1 = NULL, *chain2 = NULL;
+  GstElement *element;
+
+  /* first find the chains that hold the two  */
+  chains = sched->chains;
+  while (chains) {
+    chain = (GstSchedulerChain *) (chains->data);
+    chains = g_list_next (chains);
+
+    if (g_list_find (chain->disabled, element1))
+      chain1 = chain;
+    else if (g_list_find (chain->elements, element1))
+      chain1 = chain;
+
+    if (g_list_find (chain->disabled, element2))
+      chain2 = chain;
+    else if (g_list_find (chain->elements, element2))
+      chain2 = chain;
+  }
+
+  /* first check to see if they're in the same chain, we're done if that's the case */
+  if ((chain1 != NULL) && (chain1 == chain2)) {
+    GST_INFO (GST_CAT_SCHEDULING, "elements are already in the same chain");
+    return;
+  }
+
+  /* now, if neither element has a chain, create one */
+  if ((chain1 == NULL) && (chain2 == NULL)) {
+    GST_INFO (GST_CAT_SCHEDULING, "creating new chain to hold two new elements");
+    chain = gst_fast_scheduler_chain_new (sched);
+    gst_fast_scheduler_chain_add_element (chain, element1);
+    gst_fast_scheduler_chain_add_element (chain, element2);
+
+    /* otherwise if both have chains already, join them */
+  }
+  else if ((chain1 != NULL) && (chain2 != NULL)) {
+    GST_INFO (GST_CAT_SCHEDULING, "merging chain %p into chain %p", chain2, chain1);
+    /* take the contents of chain2 and merge them into chain1 */
+    chain1->disabled = g_list_concat (chain1->disabled, g_list_copy (chain2->disabled));
+    chain1->elements = g_list_concat (chain1->elements, g_list_copy (chain2->elements));
+    //chain1->cothreaded_elements = g_list_concat (chain1->cothreaded_elements, g_list_copy (chain2->cothreaded_elements));
+    chain1->num_elements += chain2->num_elements;
+    //chain1->num_cothreaded += chain2->num_cothreaded;
+
+    gst_fast_scheduler_chain_destroy (chain2);
+
+    /* otherwise one has a chain already, the other doesn't */
+  }
+  else {
+    /* pick out which one has the chain, and which doesn't */
+    if (chain1 != NULL)
+      chain = chain1, element = element2;
+    else
+      chain = chain2, element = element1;
+
+    GST_INFO (GST_CAT_SCHEDULING, "adding element to existing chain");
+    gst_fast_scheduler_chain_add_element (chain, element);
+  }
+}
+
+
+/* find the chain within the scheduler that holds the element, if any */
+static GstSchedulerChain *
+gst_fast_scheduler_find_chain (GstFastScheduler * sched, GstElement * element)
+{
+  GList *chains;
+  GstSchedulerChain *chain;
+
+  GST_INFO (GST_CAT_SCHEDULING, "searching for element \"%s\" in chains",
+           GST_ELEMENT_NAME (element));
+
+  chains = sched->chains;
+  while (chains) {
+    chain = (GstSchedulerChain *) (chains->data);
+    chains = g_list_next (chains);
+
+    if (g_list_find (chain->elements, element))
+      return chain;
+    if (g_list_find (chain->disabled, element))
+      return chain;
+  }
+
+  return NULL;
+}
+
+static void
+gst_fast_scheduler_chain_recursive_add (GstSchedulerChain * chain, GstElement * element)
+{
+  GList *pads;
+  GstPad *pad;
+  GstElement *peerelement;
+
+  /* add the element to the chain */
+  gst_fast_scheduler_chain_add_element (chain, element);
+
+  GST_DEBUG (GST_CAT_SCHEDULING, "recursing on element \"%s\"\n", GST_ELEMENT_NAME (element));
+  /* now go through all the pads and see which peers can be added */
+  pads = element->pads;
+  while (pads) {
+    pad = GST_PAD (pads->data);
+    pads = g_list_next (pads);
+
+    GST_DEBUG (GST_CAT_SCHEDULING, "have pad %s:%s, checking for valid peer\n",
+              GST_DEBUG_PAD_NAME (pad));
+    /* if the peer exists and could be in the same chain */
+    if (GST_PAD_PEER (pad)) {
+      GST_DEBUG (GST_CAT_SCHEDULING, "has peer %s:%s\n", GST_DEBUG_PAD_NAME (GST_PAD_PEER (pad)));
+      peerelement = GST_PAD_PARENT (GST_PAD_PEER (pad));
+      if (GST_ELEMENT_SCHED (GST_PAD_PARENT (pad)) == GST_ELEMENT_SCHED (peerelement)) {
+       GST_DEBUG (GST_CAT_SCHEDULING, "peer \"%s\" is valid for same chain\n",
+                  GST_ELEMENT_NAME (peerelement));
+       /* if it's not already in a chain, add it to this one */
+       if (gst_fast_scheduler_find_chain (chain->sched, peerelement) == NULL) {
+         gst_fast_scheduler_chain_recursive_add (chain, peerelement);
+       }
+      }
+    }
+  }
+}
+
+/*
+ * Entry points for this scheduler.
+ */
+static void
+gst_fast_scheduler_setup (GstScheduler *sched)
+{
+  GstBin *bin = GST_BIN (sched->parent);
+
+  /* first create thread context */
+  if (GST_BIN_THREADCONTEXT (bin) == NULL) {
+    GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
+    GST_BIN_THREADCONTEXT (bin) = cothread_context_init ();
+  }
+}
+
+static void
+gst_fast_scheduler_reset (GstScheduler *sched)
+{
+  cothread_context *ctx;
+  GstBin *bin = GST_BIN (GST_SCHEDULER_PARENT (sched));
+  GList *elements = GST_FAST_SCHEDULER_CAST (sched)->elements;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  while (elements) {
+    GST_ELEMENT_THREADSTATE (elements->data) = NULL;
+    elements = g_list_next (elements);
+  }
+  
+  ctx = GST_BIN_THREADCONTEXT (GST_SCHEDULER_PARENT (sched));
+
+  cothread_context_free (ctx);
+  
+  GST_BIN_THREADCONTEXT (GST_SCHEDULER_PARENT (sched)) = NULL;
+}
+
+static void
+gst_fast_scheduler_add_element (GstScheduler * sched, GstElement * element)
+{
+  GList *pads;
+  GstPad *pad;
+  GstElement *peerelement;
+  GstSchedulerChain *chain;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  /* if it's already in this scheduler, don't bother doing anything */
+  if (GST_ELEMENT_SCHED (element) == sched)
+    return;
+
+  GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to scheduler", GST_ELEMENT_NAME (element));
+
+  /* if the element already has a different scheduler, remove the element from it */
+  if (GST_ELEMENT_SCHED (element)) {
+    gst_fast_scheduler_remove_element (GST_ELEMENT_SCHED (element), element);
+  }
+
+  /* set the sched pointer in the element itself */
+  GST_ELEMENT_SCHED (element) = sched;
+
+  /* only deal with elements after this point, not bins */
+  /* exception is made for Bin's that are schedulable, like the autoplugger */
+  if (GST_IS_BIN (element) && !GST_FLAG_IS_SET (element, GST_BIN_SELF_SCHEDULABLE))
+    return;
+
+  /* first add it to the list of elements that are to be scheduled */
+  bsched->elements = g_list_prepend (bsched->elements, element);
+  bsched->num_elements++;
+
+  /* create a chain to hold it, and add */
+  chain = gst_fast_scheduler_chain_new (bsched);
+  gst_fast_scheduler_chain_add_element (chain, element);
+
+  /* set the sched pointer in all the pads */
+  pads = element->pads;
+  while (pads) {
+    pad = GST_PAD (pads->data);
+    pads = g_list_next (pads);
+
+    /* we only operate on real pads */
+    if (!GST_IS_REAL_PAD (pad))
+      continue;
+
+    /* set the pad's sched pointer */
+    gst_pad_set_sched (pad, sched);
+
+    /* if the peer element exists and is a candidate */
+    if (GST_PAD_PEER (pad)) {
+      peerelement = GST_PAD_PARENT (GST_PAD_PEER (pad));
+      if (GST_ELEMENT_SCHED (element) == GST_ELEMENT_SCHED (peerelement)) {
+       GST_INFO (GST_CAT_SCHEDULING, "peer is in same scheduler, chaining together");
+       /* make sure that the two elements are in the same chain */
+       gst_fast_scheduler_chain_elements (bsched, element, peerelement);
+      }
+    }
+  }
+}
+
+static void
+gst_fast_scheduler_remove_element (GstScheduler * sched, GstElement * element)
+{
+  GstSchedulerChain *chain;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  if (g_list_find (bsched->elements, element)) {
+    GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from scheduler",
+             GST_ELEMENT_NAME (element));
+
+    /* find what chain the element is in */
+    chain = gst_fast_scheduler_find_chain (bsched, element);
+
+    /* remove it from its chain */
+    gst_fast_scheduler_chain_remove_element (chain, element);
+
+    /* remove it from the list of elements */
+    bsched->elements = g_list_remove (bsched->elements, element);
+    bsched->num_elements--;
+
+    /* unset the scheduler pointer in the element */
+    GST_ELEMENT_SCHED (element) = NULL;
+  }
+}
+
+static GstElementStateReturn
+gst_fast_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition)
+{
+  GstSchedulerChain *chain;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  /* check if our parent changed state */
+  if (GST_SCHEDULER_PARENT (sched) == element) {
+    GST_INFO (GST_CAT_SCHEDULING, "parent \"%s\" changed state", GST_ELEMENT_NAME (element));
+    if (transition == GST_STATE_PLAYING_TO_PAUSED) {
+      GST_INFO (GST_CAT_SCHEDULING, "setting scheduler state to stopped");
+      GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_STOPPED;
+    }
+    else if (transition == GST_STATE_PAUSED_TO_PLAYING) {
+      GST_INFO (GST_CAT_SCHEDULING, "setting scheduler state to running");
+      GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_RUNNING;
+    }
+    else {
+      GST_INFO (GST_CAT_SCHEDULING, "no interesting state change, doing nothing");
+    }
+  }
+  else if (transition == GST_STATE_PLAYING_TO_PAUSED ||
+           transition == GST_STATE_PAUSED_TO_PLAYING) {
+    /* find the chain the element is in */
+    chain = gst_fast_scheduler_find_chain (bsched, element);
+
+    /* remove it from the chain */
+    if (chain) {
+      if (transition == GST_STATE_PLAYING_TO_PAUSED) {
+        gst_fast_scheduler_chain_disable_element (chain, element);
+      }
+      else if (transition == GST_STATE_PAUSED_TO_PLAYING) {
+        if (!gst_fast_scheduler_chain_enable_element (chain, element)) {
+          GST_INFO (GST_CAT_SCHEDULING, "could not enable element \"%s\"", GST_ELEMENT_NAME (element));
+          return GST_STATE_FAILURE;
+        }
+      }
+    }
+    else {
+      GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, no state change", GST_ELEMENT_NAME (element));
+    }
+  }
+
+  return GST_STATE_SUCCESS;
+}
+
+static void
+gst_fast_scheduler_lock_element (GstScheduler * sched, GstElement * element)
+{
+  if (GST_ELEMENT_THREADSTATE (element))
+    cothread_lock (GST_ELEMENT_THREADSTATE (element));
+}
+
+static void
+gst_fast_scheduler_unlock_element (GstScheduler * sched, GstElement * element)
+{
+  if (GST_ELEMENT_THREADSTATE (element))
+    cothread_unlock (GST_ELEMENT_THREADSTATE (element));
+}
+
+static void
+gst_fast_scheduler_yield (GstScheduler *sched, GstElement *element)
+{
+  if (GST_ELEMENT_IS_COTHREAD_STOPPING (element)) {
+    cothread_switch (cothread_current_main ());
+  }
+}
+
+static gboolean
+gst_fast_scheduler_interrupt (GstScheduler *sched, GstElement *element)
+{
+  if (cothread_current () != cothread_current_main()) {
+    cothread_switch (cothread_current_main ());
+    return FALSE;
+  }
+  GST_FLAG_SET (element, GST_ELEMENT_INTERRUPTED);
+  return TRUE;
+}
+
+static void
+gst_fast_scheduler_error (GstScheduler *sched, GstElement *element)
+{
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+  GstSchedulerChain *chain;
+    
+  chain = gst_fast_scheduler_find_chain (bsched, element);
+  if (chain)
+    gst_fast_scheduler_chain_disable_element (chain, element);
+
+  GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_ERROR;
+
+  gst_fast_scheduler_interrupt (sched, element);
+}
+
+static void
+gst_fast_scheduler_pad_connect (GstScheduler * sched, GstPad *srcpad, GstPad *sinkpad)
+{
+  GstElement *srcelement, *sinkelement;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  srcelement = GST_PAD_PARENT (srcpad);
+  g_return_if_fail (srcelement != NULL);
+  sinkelement = GST_PAD_PARENT (sinkpad);
+  g_return_if_fail (sinkelement != NULL);
+
+  GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s to %s:%s",
+           GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+  GST_DEBUG (GST_CAT_SCHEDULING, "srcpad sched is %p, sinkpad sched is %p\n",
+            GST_ELEMENT_SCHED (srcelement), GST_ELEMENT_SCHED (sinkelement));
+
+  if (GST_ELEMENT_SCHED (srcelement) == GST_ELEMENT_SCHED (sinkelement)) {
+    GST_INFO (GST_CAT_SCHEDULING, "peer %s:%s is in same scheduler, chaining together",
+             GST_DEBUG_PAD_NAME (sinkpad));
+    gst_fast_scheduler_chain_elements (bsched, srcelement, sinkelement);
+  }
+}
+
+static void
+gst_fast_scheduler_pad_disconnect (GstScheduler * sched, GstPad * srcpad, GstPad * sinkpad)
+{
+  GstSchedulerChain *chain;
+  GstElement *element1, *element2;
+  GstSchedulerChain *chain1, *chain2;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  GST_INFO (GST_CAT_SCHEDULING, "disconnecting pads %s:%s and %s:%s",
+           GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
+  /* we need to have the parent elements of each pad */
+  element1 = GST_ELEMENT_CAST (GST_PAD_PARENT (srcpad));
+  element2 = GST_ELEMENT_CAST (GST_PAD_PARENT (sinkpad));
+
+  /* first task is to remove the old chain they belonged to.
+   * this can be accomplished by taking either of the elements,
+   * since they are guaranteed to be in the same chain
+   * FIXME is it potentially better to make an attempt at splitting cleaner??
+   */
+  chain1 = gst_fast_scheduler_find_chain (bsched, element1);
+  chain2 = gst_fast_scheduler_find_chain (bsched, element2);
+
+  if (chain1 != chain2) {
+    /* elements not in the same chain don't need to be separated */
+    GST_INFO (GST_CAT_SCHEDULING, "elements not in the same chain");
+    return;
+  }
+
+  if (chain1) {
+    GST_INFO (GST_CAT_SCHEDULING, "destroying chain");
+    gst_fast_scheduler_chain_destroy (chain1);
+
+    /* now create a new chain to hold element1 and build it from scratch */
+    chain1 = gst_fast_scheduler_chain_new (bsched);
+    gst_fast_scheduler_chain_recursive_add (chain1, element1);
+  }
+
+  /* check the other element to see if it landed in the newly created chain */
+  if (gst_fast_scheduler_find_chain (bsched, element2) == NULL) {
+    /* if not in chain, create chain and build from scratch */
+    chain2 = gst_fast_scheduler_chain_new (bsched);
+    gst_fast_scheduler_chain_recursive_add (chain2, element2);
+  }
+}
+
+static GstPad *
+gst_fast_scheduler_pad_select (GstScheduler * sched, GList * padlist)
+{
+  GstPad *pad = NULL;
+  GList *padlist2 = padlist;
+
+  GST_INFO (GST_CAT_SCHEDULING, "imlement me!!");
+
+  return pad;
+}
+
+static GstSchedulerState
+gst_fast_scheduler_iterate (GstScheduler * sched)
+{
+  GstBin *bin = GST_BIN (sched->parent);
+  GList *chains;
+  GstSchedulerChain *chain;
+  GstElement *entry;
+  GList *elements;
+  gint scheduled = 0;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+  GstSchedulerState state;
+
+  GST_DEBUG_ENTER ("(\"%s\")", GST_ELEMENT_NAME (bin));
+
+  /* step through all the chains */
+  chains = bsched->chains;
+
+  if (chains == NULL) {
+    GST_DEBUG (GST_CAT_DATAFLOW, "no chains!\n");
+
+    state = GST_SCHEDULER_STATE_STOPPED;
+
+    goto exit;
+  }
+
+  while (chains) {
+    chain = (GstSchedulerChain *) (chains->data);
+    chains = g_list_next (chains);
+
+    if (chain->elements == NULL) {
+      continue;
+    }
+
+    //if (chain->num_cothreaded > 1) {
+    if (FALSE) {
+      g_warning ("this scheduler can only deal with 1 cothreaded element in a chain");
+
+      state = GST_SCHEDULER_STATE_ERROR;
+
+      goto exit;
+    }
+    else if (chain->num_cothreaded != 0) {
+      /* we just pick the first cothreaded element */
+      GstElement *entry = GST_ELEMENT (chain->cothreaded_elements->data);
+         
+      GST_DEBUG (GST_CAT_DATAFLOW, "starting iteration via cothreads\n");
+
+      GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING);
+
+      GST_DEBUG (GST_CAT_DATAFLOW, "set COTHREAD_STOPPING flag on \"%s\"(@%p)\n",
+                  GST_ELEMENT_NAME (entry), entry);
+
+      if (GST_ELEMENT_THREADSTATE (entry)) {
+        cothread_switch (GST_ELEMENT_THREADSTATE (entry));
+      }
+      else {
+       GST_DEBUG (GST_CAT_DATAFLOW, "cothread switch not possible, element has no threadstate\n");
+
+        GST_DEBUG (GST_CAT_DATAFLOW, "leaving (%s)\n", GST_ELEMENT_NAME (bin));
+
+       state = GST_SCHEDULER_STATE_ERROR;
+
+        goto exit;
+      }
+
+      GST_DEBUG (GST_CAT_SCHEDULING, "loopfunc of element %s ended\n", GST_ELEMENT_NAME (entry));
+
+      scheduled++;
+    }
+    else {
+      GstElement *entry = chain->entry;
+      if (entry) {
+        GList *pads = gst_element_get_pad_list (entry);
+
+        GST_DEBUG (GST_CAT_DATAFLOW, "starting chained iteration\n");
+
+        while (pads) {
+          GstPad *pad = GST_PAD_CAST (pads->data);
+         pads = g_list_next (pads);
+
+         if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
+           GstBuffer *buf;
+
+           buf = GST_RPAD_GETFUNC (pad) (pad);
+           if (GST_ELEMENT_IS_INTERRUPTED (entry)) {
+              GST_FLAG_UNSET (entry, GST_ELEMENT_INTERRUPTED);
+             break;
+           }
+            gst_pad_push (pad, buf);
+            scheduled++;
+         }
+        }
+      }
+      else {
+        GST_INFO (GST_CAT_DATAFLOW, "no entry found!!");
+
+        state = GST_SCHEDULER_STATE_ERROR;
+        goto exit;
+      }
+    }
+
+    state = GST_SCHEDULER_STATE (sched);
+
+    if (state != GST_SCHEDULER_STATE_RUNNING) {
+      GST_INFO (GST_CAT_DATAFLOW, "scheduler is not running, in state %d", state);
+
+      goto exit;
+    }
+  }
+
+  GST_DEBUG (GST_CAT_DATAFLOW, "leaving (%s)\n", GST_ELEMENT_NAME (bin));
+
+  if (scheduled == 0) {
+    GST_INFO (GST_CAT_DATAFLOW, "nothing was scheduled, return STOPPED");
+    state = GST_SCHEDULER_STATE_STOPPED;
+  }
+  else {
+    GST_INFO (GST_CAT_DATAFLOW, "scheduler still running, return RUNNING");
+    state = GST_SCHEDULER_STATE_RUNNING;
+  }
+
+exit:
+  GST_DEBUG (GST_CAT_DATAFLOW, "leaving (%s) %d\n", GST_ELEMENT_NAME (bin), state);
+  
+  return state;
+}
+
+
+static void
+gst_fast_scheduler_show (GstScheduler * sched)
+{
+  GList *chains, *elements;
+  GstElement *element;
+  GstSchedulerChain *chain;
+  GstFastScheduler *bsched = GST_FAST_SCHEDULER (sched);
+
+  if (sched == NULL) {
+    g_print ("scheduler doesn't exist for this element\n");
+    return;
+  }
+
+  g_return_if_fail (GST_IS_SCHEDULER (sched));
+
+  g_print ("SCHEDULER DUMP FOR MANAGING BIN \"%s\"\n", GST_ELEMENT_NAME (sched->parent));
+
+  g_print ("scheduler has %d elements in it: ", bsched->num_elements);
+  elements = bsched->elements;
+  while (elements) {
+    element = GST_ELEMENT (elements->data);
+    elements = g_list_next (elements);
+
+    g_print ("%s, ", GST_ELEMENT_NAME (element));
+  }
+  g_print ("\n");
+
+  g_print ("scheduler has %d chains in it\n", bsched->num_chains);
+  chains = bsched->chains;
+  while (chains) {
+    chain = (GstSchedulerChain *) (chains->data);
+    chains = g_list_next (chains);
+
+    g_print ("%p: ", chain);
+
+    elements = chain->disabled;
+    while (elements) {
+      element = GST_ELEMENT (elements->data);
+      elements = g_list_next (elements);
+
+      g_print ("!%s, ", GST_ELEMENT_NAME (element));
+    }
+
+    elements = chain->elements;
+    while (elements) {
+      element = GST_ELEMENT (elements->data);
+      elements = g_list_next (elements);
+
+      g_print ("%s, ", GST_ELEMENT_NAME (element));
+    }
+    g_print ("\n");
+  }
+}
index c6d0198..21f4c92 100644 (file)
@@ -46,6 +46,7 @@ enum {
   ARG_NUM_SINKS,
   ARG_SILENT,
   ARG_DUMP,
+  ARG_SYNC,
   ARG_LAST_MESSAGE,
 };
 
@@ -60,6 +61,7 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
 static void    gst_fakesink_class_init         (GstFakeSinkClass *klass);
 static void    gst_fakesink_init               (GstFakeSink *fakesink);
 
+static void    gst_fakesink_set_clock          (GstElement *element, GstClock *clock);
 static GstPad*         gst_fakesink_request_new_pad    (GstElement *element, GstPadTemplate *templ, const
                                                  gchar *unused);
 
@@ -106,12 +108,14 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SINKS,
-    g_param_spec_int ("num_sinks", "num_sinks", "num_sinks",
+    g_param_spec_int ("num_sinks", "Number of sinks", "The number of sinkpads",
                       1, G_MAXINT, 1, G_PARAM_READABLE)); 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
     g_param_spec_string ("last_message", "last_message", "last_message",
                          NULL, G_PARAM_READABLE));
-
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SYNC,
+    g_param_spec_boolean("sync","Sync","Sync on the clock",
+                         FALSE, G_PARAM_READWRITE)); /* CHECKME */
 
   gst_element_class_install_std_props (
          GST_ELEMENT_CLASS (klass),
@@ -141,9 +145,22 @@ gst_fakesink_init (GstFakeSink *fakesink)
 
   fakesink->silent = FALSE;
   fakesink->dump = FALSE;
+  fakesink->sync = FALSE;
   fakesink->last_message = NULL;
+
+  GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
 }
 
+static void
+gst_fakesink_set_clock (GstElement *element, GstClock *clock)
+{ 
+  GstFakeSink *sink;
+
+  sink = GST_FAKESINK (element);
+
+  sink->clock = clock;
+} 
+
 static GstPad*
 gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
 {
@@ -183,6 +200,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
     case ARG_DUMP:
       sink->dump = g_value_get_boolean (value);
       break;
+    case ARG_SYNC:
+      sink->sync = g_value_get_boolean (value);
+      break;
     default:
       break;
   }
@@ -208,6 +228,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
     case ARG_DUMP:
       g_value_set_boolean (value, sink->dump);
       break;
+    case ARG_SYNC:
+      g_value_set_boolean (value, sink->sync);
+      break;
     case ARG_LAST_MESSAGE:
       g_value_set_string (value, sink->last_message);
       break;
@@ -228,9 +251,12 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
 
   fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
 
+  if (fakesink->sync) { 
+    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
+  }
+
   if (!fakesink->silent) { 
-    if (fakesink->last_message) 
-      g_free (fakesink->last_message);
+    g_free (fakesink->last_message);
 
     fakesink->last_message = g_strdup_printf ("chain   ******* (%s:%s)< (%d bytes, %lld) %p",
                GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
index 4bc3bb5..6c38ae3 100644 (file)
@@ -52,11 +52,14 @@ typedef struct _GstFakeSink GstFakeSink;
 typedef struct _GstFakeSinkClass GstFakeSinkClass;
 
 struct _GstFakeSink {
-  GstElement element;
+  GstElement    element;
 
-  gboolean silent;
-  gboolean dump;
-  gchar    *last_message;
+  gboolean      silent;
+  gboolean      dump;
+  gboolean      sync;
+  GstClock     *clock;
+
+  gchar        *last_message;
 };
 
 struct _GstFakeSinkClass {
index 18ef726..9686385 100644 (file)
@@ -321,6 +321,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
+
       if (!GST_EVENT_SEEK_FLUSH (event)) {
         gst_event_free (event);
         break;
index 7f916ca..f4a0e67 100644 (file)
@@ -105,7 +105,8 @@ struct _GstFakeSrc {
   gboolean     silent;
   gboolean     dump;
   gboolean     need_flush;
-  gchar         *last_message;
+
+  gchar                *last_message;
 };
 
 struct _GstFakeSrcClass {
index 3f97331..c50e8c5 100644 (file)
@@ -78,7 +78,7 @@ GstElementDetails gst_filesrc_details = {
   "(C) 1999",
 };
 
-/*#define fs_print(format,args...) g_print(format, ## args)*/
+/*#define fs_print(format,args...) g_print(format, ## args) */
 #define fs_print(format,args...)
 
 /* FileSrc signals and args */
@@ -549,7 +549,7 @@ gst_filesrc_get (GstPad *pad)
 
   /* we're done, return the buffer */
   src->curoffset += GST_BUFFER_SIZE(buf);
-  g_object_notify (G_OBJECT (src), "offset");
+  //g_object_notify (G_OBJECT (src), "offset");
   return buf;
 }
 
@@ -590,7 +590,7 @@ gst_filesrc_open_file (GstFileSrc *src)
     /* now notify of the changes */
     g_object_freeze_notify (G_OBJECT (src));
     g_object_notify (G_OBJECT (src), "filesize");
-    g_object_notify (G_OBJECT (src), "offset");
+    //g_object_notify (G_OBJECT (src), "offset");
     g_object_thaw_notify (G_OBJECT (src));
 
     GST_FLAG_SET (src, GST_FILESRC_OPEN);
@@ -614,7 +614,7 @@ gst_filesrc_close_file (GstFileSrc *src)
   /* and notify that things changed */
   g_object_freeze_notify (G_OBJECT (src));
   g_object_notify (G_OBJECT (src), "filesize");
-  g_object_notify (G_OBJECT (src), "offset");
+  //g_object_notify (G_OBJECT (src), "offset");
   g_object_thaw_notify (G_OBJECT (src));
 
   if (src->mapbuf)
index 3540743..cf8ec85 100644 (file)
@@ -83,7 +83,6 @@ static GstBuffer *            gst_queue_get                   (GstPad *pad);
 static GstBufferPool*          gst_queue_get_bufferpool        (GstPad *pad);
        
 static void                    gst_queue_locked_flush                  (GstQueue *queue);
-static void                    gst_queue_flush                 (GstQueue *queue);
 
 static GstElementStateReturn   gst_queue_change_state          (GstElement *element);
 
@@ -275,15 +274,6 @@ gst_queue_locked_flush (GstQueue *queue)
 }
 
 static void
-gst_queue_flush (GstQueue *queue)
-{
-  g_mutex_lock (queue->qlock);
-  gst_queue_locked_flush (queue);
-  g_mutex_unlock (queue->qlock);
-}
-
-
-static void
 gst_queue_chain (GstPad *pad, GstBuffer *buf)
 {
   GstQueue *queue;
@@ -378,7 +368,7 @@ restart:
          return;
        }
        else {
-          gst_element_info (GST_ELEMENT (queue), "waiting for the app to restart source pad elements");
+          g_print ("%s: waiting for the app to restart source pad elements\n", GST_ELEMENT_NAME (queue));
        }
       }
 
@@ -459,7 +449,7 @@ restart:
         goto restart;
       }
       else {
-        gst_element_info (GST_ELEMENT (queue), "waiting for the app to restart sink pad elements");
+        g_print ("%s: waiting for the app to restart source pad elements\n", GST_ELEMENT_NAME (queue));
       }
     }
 
index ea38edc..2ea7428 100644 (file)
@@ -181,7 +181,7 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
   GList *pads;
 
   g_return_val_if_fail (GST_IS_TEE (element), NULL);
-
+  
   if (templ->direction != GST_PAD_SRC) {
     g_warning ("gsttee: request new pad that is not a SRC pad\n");
     return NULL;