Megapatch, changes which states are available, how they're used, and how they're...
authorErik Walthinsen <omega@temple-baptist.org>
Mon, 17 Jul 2000 17:14:15 +0000 (17:14 +0000)
committerErik Walthinsen <omega@temple-baptist.org>
Mon, 17 Jul 2000 17:14:15 +0000 (17:14 +0000)
Original commit message from CVS:
Megapatch, changes which states are available, how they're used, and how
they're set.  Also modifies the scheduling system, breaking pulled
buffers.  Check mail archives for more details.

30 files changed:
Makefile.am
autogen.sh
configure.in
docs/Makefile.am
docs/gst/gstreamer-decl.txt
gst/Makefile.am
gst/elements/gstelements.c
gst/elements/gstfakesink.c
gst/elements/gstfakesrc.c
gst/gstbin.c
gst/gstbin.h
gst/gstclock.c
gst/gstelement.c
gst/gstelement.h
gst/gstpad.c
gst/gstpad.h
gst/gstpipeline.c
gst/gstthread.c
gst/gstthread.h
plugins/elements/gstelements.c
plugins/elements/gstfakesink.c
plugins/elements/gstfakesrc.c
test/fake.c
tests/.gitignore [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/README [new file with mode: 0644]
tests/init.c [new file with mode: 0644]
tests/loadall.c [new file with mode: 0644]
tests/simplefake.c [new file with mode: 0644]
tests/states.c [new file with mode: 0644]

index 803a9b6..c921e49 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = gst plugins test editor tools docs libs
+SUBDIRS = gst libs plugins test editor tools docs tests
 
 bin_SCRIPTS = gstreamer-config
 
index 1e0e7be..2862b7e 100755 (executable)
@@ -61,7 +61,7 @@ for dir in `find * -name autogen.sh -print | grep -v '^autogen.sh$' | \
   popd > /dev/null
 done
 
-./configure --enable-maintainer-mode "$@"
+./configure --enable-maintainer-mode --enable-debug "$@"
 
 echo 
 echo "Now type 'make' to compile $package."
index 95df3ec..2d50067 100644 (file)
@@ -51,7 +51,7 @@ AM_PATH_GLIB(1.2.0,,
             glib gmodule gthread)
 dnl Put the glib flags into $LIBS and $CFLAGS since we always use them
 LIBS="$LIBS $GLIB_LIBS"
-CFLAGS="$FLAGS $GLIB_CFLAGS"
+CFLAGS="$CFLAGS $GLIB_CFLAGS"
 
 dnl Check for libxml
 AC_PATH_PROG(XML_CONFIG, xml-config, no)
@@ -306,7 +306,7 @@ AM_CONDITIONAL(HAVE_LIBMMX,     test "x$USE_LIBMMX" = "xyes")
 AM_CONDITIONAL(HAVE_ATOMIC_H,   test "x$USE_ATOMIC_H" = "xyes")
 AM_CONDITIONAL(HAVE_XAUDIO,     test "x$HAVE_XAUDIO" = "xyes")
 AM_CONDITIONAL(HAVE_CSSAUTH,    test "x$HAVE_CSSAUTH" = "xyes")
-AM_CONDITIONAL(HAVE_GTK_DOC,    $HAVE_GTK_DOC)
+AM_CONDITIONAL(HAVE_GTK_DOC,    test "x$HAVE_GTK_DOC" = "xyes")
 
 
 dnl FIXME: having to AC_SUBST these is messy.  Not sure if CPPFLAGS and LDFLAGS
index 9e35835..07c33b2 100644 (file)
@@ -1,8 +1,8 @@
 SUBDIRS = 
 if HAVE_GTK_DOC
-  SUBDIRS += gst 
+  SUBDIRS += gst manual
 endif
 
-DIST_SUBDIRS = gst
+DIST_SUBDIRS = gst manual
 
 EXTRA_DIST = random slides
index ce2f17a..590d997 100644 (file)
@@ -136,25 +136,6 @@ struct GstBin {
   cothread_context *threadcontext;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstBinClass</NAME>
-struct GstBinClass {
-  GstElementClass parent_class;
-
-  void (*object_added) (GstObject *object,GstObject *child);
-
-  /* change the state of elements of the given type */
-  gboolean (*change_state_type) (GstBin *bin,
-                                 GstElementState state,
-                                 GtkType type);
-
-  /* create a plan for the execution of the bin */
-  void (*create_plan) (GstBin *bin);
-
-  /* run a full iteration of operation */
-  void (*iterate) (GstBin *bin);
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_bin_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -359,64 +340,6 @@ GstBuffer *buffer
 <RETURNS>void  </RETURNS>
 GstBuffer *buffer,GstMeta *meta
 </FUNCTION>
-<TYPEDEF>
-<NAME>GstClockTime</NAME>
-typedef guint64 GstClockTime;
-</TYPEDEF>
-<TYPEDEF>
-<NAME>GstClockTimeDiff</NAME>
-typedef gint64 GstClockTimeDiff;
-</TYPEDEF>
-<MACRO>
-<NAME>GST_CLOCK_DIFF</NAME>
-#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
-</MACRO>
-<STRUCT>
-<NAME>GstClock</NAME>
-</STRUCT>
-<STRUCT>
-<NAME>GstClock</NAME>
-struct GstClock {
-  gchar *name;
-  GstClockTime start_time;
-  GstClockTime current_time;
-  GstClockTimeDiff adjust;
-  gboolean locking;
-  GList *sinkobjects;
-  GMutex *sinkmutex;
-  GMutex *lock;
-};
-</STRUCT>
-<FUNCTION>
-<NAME>gst_clock_new</NAME>
-<RETURNS>GstClock  *</RETURNS>
-gchar *name
-</FUNCTION>
-<FUNCTION>
-<NAME>gst_clock_get_system</NAME>
-<RETURNS>GstClock  *</RETURNS>
-void
-</FUNCTION>
-<FUNCTION>
-<NAME>gst_clock_register</NAME>
-<RETURNS>void  </RETURNS>
-GstClock *clock, GstObject *obj
-</FUNCTION>
-<FUNCTION>
-<NAME>gst_clock_set</NAME>
-<RETURNS>void  </RETURNS>
-GstClock *clock, GstClockTime time
-</FUNCTION>
-<FUNCTION>
-<NAME>gst_clock_reset</NAME>
-<RETURNS>void  </RETURNS>
-GstClock *clock
-</FUNCTION>
-<FUNCTION>
-<NAME>gst_clock_wait</NAME>
-<RETURNS>void  </RETURNS>
-GstClock *clock, GstClockTime time, GstObject *obj
-</FUNCTION>
 <MACRO>
 <NAME>GST_TYPE_CONNECTION</NAME>
 #define GST_TYPE_CONNECTION \
@@ -454,15 +377,6 @@ struct GstConnection {
   GstElement element;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstConnectionClass</NAME>
-struct GstConnectionClass {
-  GstElementClass parent_class;
-
-  /* push function */
-  void (*push) (GstConnection *connection);
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_connection_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -504,14 +418,16 @@ typedef enum {
 <NAME>GST_STATE_SET</NAME>
 #define GST_STATE_SET(obj,flag) \
 G_STMT_START{ (GST_STATE (obj) |= (flag)); \
-gst_info("set '%s' state %d\n",gst_element_get_name(obj),flag); \
+gst_info("set '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
+_gst_print_statename(flag)); \
 }G_STMT_END
 </MACRO>
 <MACRO>
 <NAME>GST_STATE_UNSET</NAME>
 #define GST_STATE_UNSET(obj,flag) \
 G_STMT_START{ (GST_STATE (obj) &= ~(flag)); \
-gst_info("unset '%s' state %d\n",gst_element_get_name(obj),flag); \
+gst_info("unset '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
+_gst_print_statename(flag)); \
 }G_STMT_END
 </MACRO>
 <MACRO>
@@ -539,6 +455,16 @@ gst_info("unset '%s' state %d\n",gst_element_get_name(obj),flag); \
 #define GST_IS_ELEMENT_CLASS(obj) \
   (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
 </MACRO>
+<ENUM>
+<NAME>GstElementFlags</NAME>
+typedef enum {
+  GST_ELEMENT_MULTI_OUT                = (1 << 16),
+} GstElementFlags;
+</ENUM>
+<MACRO>
+<NAME>GST_ELEMENT_IS_MULTI_OUT</NAME>
+#define GST_ELEMENT_IS_MULTI_OUT(obj)  ((GST_FLAGS(obj) & GST_ELEMENT_MULTI_OUT)
+</MACRO>
 <STRUCT>
 <NAME>GstElement</NAME>
 </STRUCT>
@@ -575,32 +501,6 @@ struct GstElement {
 };
 </STRUCT>
 <STRUCT>
-<NAME>GstElementClass</NAME>
-struct GstElementClass {
-  GstObjectClass parent_class;
-
-  /* the elementfactory that created us */
-  GstElementFactory *elementfactory;
-
-  /* signal callbacks */
-  void (*state_change) (GstElement *element,GstElementState state);
-  void (*new_pad) (GstElement *element,GstPad *pad);
-  void (*new_ghost_pad) (GstElement *element,GstPad *pad);
-  void (*error) (GstElement *element,gchar *error);
-
-  /* events */
-  gboolean (*start) (GstElement *element,GstElementState state);
-  gboolean (*stop) (GstElement *element);
-
-  /* change the element state */
-  gboolean (*change_state) (GstElement *element,GstElementState state);
-
-  /* create or read XML representation of self */
-  xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent);
-  void (*restore_thyself)(GstElement *element,xmlNodePtr *self);
-};
-</STRUCT>
-<STRUCT>
 <NAME>GstElementDetails</NAME>
 struct GstElementDetails {
   gchar *longname;              /* long, english name */
@@ -776,12 +676,6 @@ struct GstFilter {
   GstElement element;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstFilterClass</NAME>
-struct GstFilterClass {
-  GstElementClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_filter_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -926,17 +820,6 @@ struct GstObject {
   GstObject *parent;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstObjectClass</NAME>
-struct GstObjectClass {
-  GtkObjectClass parent_class;
-
-  /* signals */
-  void (*parent_set) (GstObject *object,GstObject *parent);
-
-  /* functions go here */
-};
-</STRUCT>
 <MACRO>
 <NAME>GST_FLAGS</NAME>
 #define GST_FLAGS(obj)                 GTK_OBJECT_FLAGS(obj)
@@ -1028,13 +911,11 @@ GstObject *object
 </MACRO>
 <MACRO>
 <NAME>GST_PAD_CONNECTED</NAME>
-#define GST_PAD_CONNECTED(pad) \
-       ((pad)->peer != NULL)
+#define GST_PAD_CONNECTED(pad) ((pad)->peer != NULL)
 </MACRO>
 <MACRO>
 <NAME>GST_PAD_CAN_PULL</NAME>
-#define GST_PAD_CAN_PULL(pad) \
-       ((pad)->pull != NULL)
+#define GST_PAD_CAN_PULL(pad) ((pad)->pullfunc != NULL)
 </MACRO>
 <STRUCT>
 <NAME>GstPad</NAME>
@@ -1049,7 +930,7 @@ GstPad *pad,GstBuffer *buf
 </USER_FUNCTION>
 <USER_FUNCTION>
 <NAME>GstPadPullFunction</NAME>
-<RETURNS>GstBuffer *</RETURNS>
+<RETURNS>void </RETURNS>
 GstPad *pad
 </USER_FUNCTION>
 <USER_FUNCTION>
@@ -1079,19 +960,14 @@ struct GstPad {
 
   GstBuffer *bufpen;
 
-  GstPadChainFunction chain;
-  GstPadPullFunction pull;
+  GstPadChainFunction chainfunc;
+  GstPadPullFunction pullfunc;
+  GstPadPushFunction pushfunc;
 
   GstObject *parent;
   GList *ghostparents;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstPadClass</NAME>
-struct GstPadClass {
-  GstObjectClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_pad_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1233,12 +1109,6 @@ struct GstPipeline {
   GstBin bin;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstPipelineClass</NAME>
-struct GstPipelineClass {
-  GstBinClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_pipeline_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1368,12 +1238,6 @@ struct GstSink {
   GstElement element;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstSinkClass</NAME>
-struct GstSinkClass {
-  GstElementClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_sink_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1438,19 +1302,6 @@ struct GstSrc {
   gint32 flags;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstSrcClass</NAME>
-struct GstSrcClass {
-  GstElementClass parent_class;
-
-  /* subclass functions */
-  void (*push) (GstSrc *src);
-  void (*push_region) (GstSrc *src,gulong offset,gulong size);
-
-  /* signals */
-  void (*eos) (GstSrc *src);
-};
-</STRUCT>
 <MACRO>
 <NAME>GST_SRC_SET_FLAGS</NAME>
 #define GST_SRC_SET_FLAGS(src,flag) \
@@ -1523,12 +1374,6 @@ struct GstTee {
   GSList *srcpads;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstTeeClass</NAME>
-struct GstTeeClass {
-  GstFilterClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_tee_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1593,20 +1438,11 @@ typedef enum {
 struct GstThread {
   GstBin bin;
 
-  GList *entries;              /* used to determine iterate behavior */
-  gint numentries;             /* number of above entry points */
-
   pthread_t thread_id;         /* id of the thread, if any */
   GMutex *lock;                        /* thread lock/condititon pair... */
   GCond *cond;                 /* used to control the thread */
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstThreadClass</NAME>
-struct GstThreadClass {
-  GstBinClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_thread_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1825,6 +1661,64 @@ GtkObject *object,guchar *argname
 <RETURNS>xmlDocPtr  </RETURNS>
 GstElement *element
 </FUNCTION>
+<TYPEDEF>
+<NAME>GstClockTime</NAME>
+typedef guint64 GstClockTime;
+</TYPEDEF>
+<TYPEDEF>
+<NAME>GstClockTimeDiff</NAME>
+typedef gint64 GstClockTimeDiff;
+</TYPEDEF>
+<MACRO>
+<NAME>GST_CLOCK_DIFF</NAME>
+#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
+</MACRO>
+<STRUCT>
+<NAME>GstClock</NAME>
+</STRUCT>
+<STRUCT>
+<NAME>GstClock</NAME>
+struct GstClock {
+  gchar *name;
+  GstClockTime start_time;
+  GstClockTime current_time;
+  GstClockTimeDiff adjust;
+  gboolean locking;
+  GList *sinkobjects;
+  GMutex *sinkmutex;
+  GMutex *lock;
+};
+</STRUCT>
+<FUNCTION>
+<NAME>gst_clock_new</NAME>
+<RETURNS>GstClock  *</RETURNS>
+gchar *name
+</FUNCTION>
+<FUNCTION>
+<NAME>gst_clock_get_system</NAME>
+<RETURNS>GstClock  *</RETURNS>
+void
+</FUNCTION>
+<FUNCTION>
+<NAME>gst_clock_register</NAME>
+<RETURNS>void  </RETURNS>
+GstClock *clock, GstObject *obj
+</FUNCTION>
+<FUNCTION>
+<NAME>gst_clock_set</NAME>
+<RETURNS>void  </RETURNS>
+GstClock *clock, GstClockTime time
+</FUNCTION>
+<FUNCTION>
+<NAME>gst_clock_reset</NAME>
+<RETURNS>void  </RETURNS>
+GstClock *clock
+</FUNCTION>
+<FUNCTION>
+<NAME>gst_clock_wait</NAME>
+<RETURNS>void  </RETURNS>
+GstClock *clock, GstClockTime time, GstObject *obj
+</FUNCTION>
 <MACRO>
 <NAME>GST_TYPE_ASYNCDISKSRC</NAME>
 #define GST_TYPE_ASYNCDISKSRC \
@@ -1885,12 +1779,6 @@ struct GstAsyncDiskSrc {
   gulong seq;                          /* buffer sequence number */
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstAsyncDiskSrcClass</NAME>
-struct GstAsyncDiskSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_asyncdisksrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -1944,15 +1832,6 @@ struct GstAudioSink {
   gint frequency;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstAudioSinkClass</NAME>
-struct GstAudioSinkClass {
-  GstSinkClass parent_class;
-
-  /* signals */
-  void (*handoff) (GstElement *element,GstPad *pad);
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_audiosink_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2014,12 +1893,6 @@ struct GstAudioSrc {
   MetaAudioRaw *meta;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstAudioSrcClass</NAME>
-struct GstAudioSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_audiosrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2080,12 +1953,6 @@ struct GstDiskSrc {
   gulong seq;                          /* buffer sequence number */
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstDiskSrcClass</NAME>
-struct GstDiskSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_disksrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2137,15 +2004,6 @@ struct GstEsdSink {
   gint frequency;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstEsdSinkClass</NAME>
-struct GstEsdSinkClass {
-  GstFilterClass parent_class;
-
-  /* signals */
-  void (*handoff) (GstElement *element,GstPad *pad);
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_esdsink_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2190,12 +2048,6 @@ struct GstFakeSink {
   GstPad *sinkpad;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstFakeSinkClass</NAME>
-struct GstFakeSinkClass {
-  GstSinkClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_fakesink_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2240,12 +2092,6 @@ struct GstFakeSrc {
   GstPad *srcpad;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstFakeSrcClass</NAME>
-struct GstFakeSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_fakesrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2292,12 +2138,6 @@ struct GstFdSink {
   int fd;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstFdSinkClass</NAME>
-struct GstFdSinkClass {
-  GstSinkClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_fdsink_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2350,12 +2190,6 @@ struct GstFdSrc {
   gulong seq;                          /* buffer sequence number */
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstFdSrcClass</NAME>
-struct GstFdSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_fdsrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2407,12 +2241,6 @@ struct GstHttpSrc {
   gulong bytes_per_read;               /* bytes per read */
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstHttpSrcClass</NAME>
-struct GstHttpSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_httpsrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2460,12 +2288,6 @@ struct GstIdentity {
   gint control;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstIdentityClass</NAME>
-struct GstIdentityClass {
-  GstFilterClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_identity_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2526,12 +2348,6 @@ struct GstQueue {
   GCond *fullcond;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstQueueClass</NAME>
-struct GstQueueClass {
-  GstConnectionClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_queue_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
@@ -2585,18 +2401,15 @@ struct GstSineSrc {
   gint channels;
   gint frequency;
 
+  /* state */
+  double mTheta;
+
   gulong seq;
 
   MetaAudioRaw meta;
   gboolean sentmeta;
 };
 </STRUCT>
-<STRUCT>
-<NAME>GstSineSrcClass</NAME>
-struct GstSineSrcClass {
-  GstSrcClass parent_class;
-};
-</STRUCT>
 <FUNCTION>
 <NAME>gst_sinesrc_get_type</NAME>
 <RETURNS>GtkType  </RETURNS>
index 6e48bf1..a5a994b 100644 (file)
@@ -58,6 +58,9 @@ libgstinclude_HEADERS =       \
        cothreads.h
 
 CFLAGS += -O2 -Wall
+#if USE_DEBUG
+CFLAGS += -g
+#endif
 
 libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS)
 libgst_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE)
index 1d8fc43..e7464e3 100644 (file)
@@ -45,13 +45,13 @@ struct _elements_entry {
 };
 
 struct _elements_entry _elements[] = {
+  { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
+  { "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
   { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details },
   { "audiosink", gst_audiosink_get_type, &gst_audiosink_details },
   { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details },
   { "disksrc", gst_disksrc_get_type, &gst_disksrc_details },
   { "identity", gst_identity_get_type, &gst_identity_details },
-  { "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
-  { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
   { "fdsink", gst_fdsink_get_type, &gst_fdsink_details },
   { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details },
 #if HAVE_LIBGHTTP
index 4b97c4a..7d00e60 100644 (file)
@@ -86,8 +86,8 @@ static void gst_fakesink_init(GstFakeSink *fakesink) {
   gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad);
   gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain);
 
-  // we're already complete, since we don't have any args...
-  gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE);
+  // we're ready right away, since we don't have any args...
+//  gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_READY);
 }
 
 /**
@@ -120,8 +120,8 @@ void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) {
   g_return_if_fail(buf != NULL);
 
   fakesink = GST_FAKESINK(pad->parent);
-//  g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n",
-//          buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink)));
+//  g_print("gst_fakesink_chain: got buffer in '%s'\n",
+//          gst_element_get_name(GST_ELEMENT(fakesink)));
   g_print("<");
   gst_buffer_unref(buf);
 }
index 565caa2..495f180 100644 (file)
@@ -87,8 +87,8 @@ static void gst_fakesrc_init(GstFakeSrc *fakesrc) {
   fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
   gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad);
 
-  // we're already complete, since we don't have any args...
-  gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE);
+  // we're ready right away, since we don't have any args...
+//  gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
 }
 
 /**
index b3093b5..0df2b7f 100644 (file)
@@ -31,13 +31,11 @@ GstElementDetails gst_bin_details = {
 
 void gst_bin_real_destroy(GtkObject *object);
 
-static gboolean gst_bin_change_state(GstElement *element,
-                                     GstElementState state);
+static GstElementStateReturn gst_bin_change_state(GstElement *element);
+static GstElementStateReturn gst_bin_change_state_norecurse(GstBin *bin);
 static gboolean gst_bin_change_state_type(GstBin *bin,
                                           GstElementState state,
                                           GtkType type);
-static gboolean gst_bin_change_state_norecurse(GstElement *element,
-                                     GstElementState state);
 
 static void gst_bin_create_plan_func(GstBin *bin);
 static void gst_bin_iterate_func(GstBin *bin);
@@ -143,28 +141,38 @@ void gst_bin_add(GstBin *bin,GstElement *element) {
   g_return_if_fail(element != NULL);
   g_return_if_fail(GST_IS_ELEMENT(element));
 
+  // must be NULL or PAUSED state in order to modify bin
+  g_return_if_fail((GST_STATE(bin) == GST_STATE_NULL) ||
+                  (GST_STATE(bin) == GST_STATE_PAUSED));
+
   bin->children = g_list_append(bin->children,element);
   bin->numchildren++;
   gst_object_set_parent(GST_OBJECT(element),GST_OBJECT(bin));
 
+#ifdef OLDSTATE
   /* FIXME: this isn't right, the bin should be complete whether or not
      the children are, I think. */
 //  if (GST_STATE_IS_SET(element,GST_STATE_COMPLETE)) {
     if (!GST_STATE_IS_SET(bin,GST_STATE_COMPLETE)) {
-      g_print("GstBin: adding complete element - \n");
-      gst_bin_change_state_norecurse(GST_ELEMENT(bin),GST_STATE_COMPLETE);
+      g_print("GstBin: adding complete element - ");
+      gst_bin_change_state_norecurse(GST_ELEMENT(bin));
     }
 //  } else {
 //    g_print("GstBin: adding element - ");
 //  gst_bin_change_state_norecurse(GST_ELEMENT(bin),~GST_STATE_COMPLETE);
 //  }
+#else
+  /* we know we have at least one child, we just added one... */
+//  if (GST_STATE(element) < GST_STATE_READY)
+//    gst_bin_change_state_norecurse(bin,GST_STATE_READY);
+#endif
 
   gtk_signal_emit(GTK_OBJECT(bin),gst_bin_signals[OBJECT_ADDED],element);
 }
 
 /**
  * gst_bin_remove:
- * @bin: #Gstbin to remove element from
+ * @bin: #GstBin to remove element from
  * @element: #GstElement to remove
  *
  * Remove the element from its associated bin, unparenting as well.
@@ -176,57 +184,74 @@ void gst_bin_remove(GstBin *bin,GstElement *element) {
   g_return_if_fail(GST_IS_ELEMENT(element));
   g_return_if_fail(bin->children != NULL);
 
+  // must be NULL or PAUSED state in order to modify bin
+  g_return_if_fail((GST_STATE(bin) == GST_STATE_NULL) ||
+                  (GST_STATE(bin) == GST_STATE_PAUSED));
+
   gst_object_unparent(GST_OBJECT(element));
   bin->children = g_list_remove(bin->children,element);
   bin->numchildren--;
+
+  /* if we're down to zero children, force state to NULL */
+  if (bin->numchildren == 0)
+    gst_element_set_state(GST_ELEMENT(bin),GST_STATE_NULL);
 }
 
 
-static gboolean gst_bin_change_state(GstElement *element,
-                                     GstElementState state) {
+static GstElementStateReturn gst_bin_change_state(GstElement *element) {
   GstBin *bin;
   GList *children;
   GstElement *child;
 
-//  g_print("gst_bin_change_state(\"%s\",%d);\n",
-//          gst_object_get_name(GST_OBJECT(bin)),state);
-
-  g_return_val_if_fail(GST_IS_BIN(element), FALSE);
+  g_return_val_if_fail(GST_IS_BIN(element), GST_STATE_FAILURE);
   bin = GST_BIN(element);
-  g_return_val_if_fail(bin->numchildren != 0, FALSE);
+
+  g_print("gst_bin_change_state(\"%s\"): currently %d(%s), %d(%s) pending\n",
+          gst_element_get_name(element),GST_STATE(element),
+          _gst_print_statename(GST_STATE(element)),GST_STATE_PENDING(element),
+          _gst_print_statename(GST_STATE_PENDING(element)));
+
+//  g_return_val_if_fail(bin->numchildren != 0, GST_STATE_FAILURE);
 
 //  g_print("-->\n");
   children = bin->children;
   while (children) {
     child = GST_ELEMENT(children->data);
-    //g_print("gst_bin_change_state setting state on \"%s\"\n",
-    //        gst_element_get_name(GST_ELEMENT(child)));
-    if (!gst_element_set_state(child,state)) {
-      g_print("GstBin: child %p failed to set state 0x%08x\n",child,state);
-      return FALSE;
+    g_print("gst_bin_change_state: setting state on '%s'\n",
+            gst_element_get_name(child));
+    switch (gst_element_set_state(child,GST_STATE_PENDING(element))) {
+      case GST_STATE_FAILURE:
+        GST_STATE_PENDING(element) = GST_STATE_NONE_PENDING;
+        g_print("child '%s' failed to go to state %d(%s)\n",gst_element_get_name(child),
+                GST_STATE_PENDING(element),_gst_print_statename(GST_STATE_PENDING(element)));
+        return GST_STATE_FAILURE;
+        break;
+      case GST_STATE_ASYNC:
+        g_print("child '%s' is changing state asynchronously\n",gst_element_get_name(child));
+        break;
     }
 //    g_print("\n");
     children = g_list_next(children);
   }
 //  g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin)));
 
-  if (GST_ELEMENT_CLASS(parent_class)->change_state)
-    return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
-  return TRUE;
-}
+//  if (GST_STATE_PENDING(element),
 
+  return gst_bin_change_state_norecurse(bin);
+}
 
-static gboolean gst_bin_change_state_norecurse(GstElement *element,
-                                     GstElementState state) {
-  GstBin *bin;
 
-  g_return_val_if_fail(GST_IS_BIN(element), FALSE);
-  bin = GST_BIN(element);
-  g_return_val_if_fail(bin->numchildren != 0, FALSE);
+static GstElementStateReturn gst_bin_change_state_norecurse(GstBin *bin) {
+/*
+  if ((state == GST_STATE_READY) && (GST_STATE(bin) < GST_STATE_READY)) {
+//    gst_bin_create_plan(
+  }
+*/
 
   if (GST_ELEMENT_CLASS(parent_class)->change_state)
-    return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
-  return TRUE;
+    return GST_ELEMENT_CLASS(parent_class)->change_state(bin);
+  else
+    return GST_STATE_FAILURE;
 }
 
 static gboolean gst_bin_change_state_type(GstBin *bin,
@@ -371,6 +396,7 @@ void gst_bin_iterate(GstBin *bin) {
 
   oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass);
 
+g_print("gst_bin_iterate()\n");
   if (oclass->iterate)
     (oclass->iterate)(bin);
 }
@@ -384,6 +410,7 @@ void gst_bin_create_plan(GstBin *bin) {
     (oclass->create_plan)(bin);
 }
 
+#ifdef OLD_STUFF
 static void gst_bin_create_plan_func(GstBin *bin) {
   GList *elements;
   GstElement *element;
@@ -400,7 +427,8 @@ static void gst_bin_create_plan_func(GstBin *bin) {
   while (elements) {
     element = GST_ELEMENT(elements->data);
 
-    // have to use cothreads if any elements use loop functions
+    // have to use cothreads if any elements use loop functions, or if any
+    // of them have nontrivial chain functions
     if (element->loopfunc != NULL) {
       if (bin->threadcontext == NULL) {
         g_print("GstBin: initializing cothread context\n");
@@ -414,14 +442,14 @@ static void gst_bin_create_plan_func(GstBin *bin) {
       }
     }
 
-    /* we need to find all the entry points into the bin */
+    // we need to find all the entry points into the bin
     if (GST_IS_SRC(element)) {
       g_print("GstBin: element '%s' is a source entry point for the bin\n",
               gst_element_get_name(GST_ELEMENT(element)));
       bin->entries = g_list_prepend(bin->entries,element);
       bin->numentries++;
     } else {
-      /* go through the list of pads to see if there's a Connection */
+      // go through the list of pads to see if there's a Connection
       pads = gst_element_get_pad_list(element);
       while (pads) {
         pad = GST_PAD(pads->data);
@@ -449,31 +477,187 @@ for internal element '%s'\n",
     }
     elements = g_list_next(elements);
   }
-  g_print("GstBin: have %d entries into bin\n",bin->numentries);
+  g_print("have %d entries into bin\n",bin->numentries);
+}
+#endif
+
+static int gst_bin_loopfunc_wrapper(int argc,char *argv[]) {
+  GstElement *element = GST_ELEMENT(argv);
+  GList *pads;
+  GstPad *pad;
+  GstBuffer *buf;
+
+//  g_print("** gst_bin_loopfunc_wrapper(%d,\"%s\")\n",
+//          argc,gst_element_get_name(element));
+
+  if (element->loopfunc != NULL) {
+//    g_print("** gst_bin_loopfunc_wrapper(): element has loop function, calling it\n");
+    while (1) {
+      (element->loopfunc)(element);
+    }
+  } else {
+//    g_print("** gst_bin_loopfunc_wrapper(): element is chain-based, calling in infinite loop\n");
+    if (GST_IS_SRC(element)) {
+      while (1) {
+//        g_print("** gst_bin_loopfunc_wrapper(): calling push function of source\n");
+        gst_src_push(GST_SRC(element));
+      }
+    } else {
+      while (1) {
+        pads = element->pads;
+        while (pads) {
+          pad = GST_PAD(pads->data);
+          if (pad->direction == GST_PAD_SINK) {
+//            g_print("** gst_bin_loopfunc_wrapper(): pulling a buffer\n");
+            buf = gst_pad_pull(pad);
+//            g_print("** gst_bin_loopfunc_wrapper(): calling chain function\n");
+            (pad->chainfunc)(pad,buf);
+          }
+          pads = g_list_next(pads);
+        }
+      }
+    }
+  }
+}
+
+static void gst_bin_pullfunc_wrapper(GstPad *pad) {
+//  g_print("** in gst_bin_pullfunc_wrapper()============================= %s\n",
+//          gst_element_get_name(GST_ELEMENT(pad->parent)));
+  cothread_switch(GST_ELEMENT(pad->parent)->threadstate);
+}
+
+static void gst_bin_pushfunc_wrapper(GstPad *pad) {
+//  g_print("** in gst_bin_pushfunc_wrapper()============================= %s\n",
+//          gst_element_get_name(GST_ELEMENT(pad->parent)));
+  cothread_switch(GST_ELEMENT(pad->parent)->threadstate);
+}
+
+static void gst_bin_create_plan_func(GstBin *bin) {
+  GList *elements;
+  GstElement *element;
+  int sink_pads;
+  GList *pads;
+  GstPad *pad, *peer;
+  GstElement *outside;
+
+  g_print("creating plan for bin\n");
+
+  // first loop through all children to see if we need cothreads
+  // we break immediately when we find we need to, why keep searching?
+  elements = bin->children;
+  while (elements) {
+    element = GST_ELEMENT(elements->data);
+    // if it's a loop-based element, use cothreads
+    if (element->loopfunc != NULL) {
+      bin->need_cothreads = TRUE;
+      break;
+    }
+    // if it's a complex element, use cothreads
+    if (GST_ELEMENT_IS_MULTI_IN(element)) {
+      bin->need_cothreads = TRUE;
+      break;
+    }
+    // if it has more than one input pad, use cothreads
+    sink_pads = 0;
+    pads = gst_element_get_pad_list(element);
+    while (pads) {
+      pad = GST_PAD(pads->data);
+      if (pad->direction == GST_PAD_SINK)
+        sink_pads++;
+      pads = g_list_next(pads);
+    }
+    if (sink_pads > 1) {
+      bin->need_cothreads = TRUE;
+      break;
+    }
+    elements = g_list_next(elements);
+  }
+
+  if (bin->need_cothreads) {
+    g_print("BIN: need cothreads\n");
+
+    // first create thread context
+    if (bin->threadcontext == NULL) {
+      bin->threadcontext = cothread_init();
+      g_print("initialized cothread context\n");
+    }
+
+    // walk through all the children
+    elements = bin->children;
+    while (elements) {
+      element = GST_ELEMENT(elements->data);
+
+      // start by creating thread state for the element
+      if (element->threadstate == NULL) {
+        element->threadstate = cothread_create(bin->threadcontext);
+        cothread_setfunc(element->threadstate,gst_bin_loopfunc_wrapper,
+                         0,(char **)element);
+      }
+
+      pads = gst_element_get_pad_list(element);
+      while (pads) {
+        pad = GST_PAD(pads->data);
+g_print("setting push&pull handlers for %s:%s\n",
+gst_element_get_name(element),gst_pad_get_name(pad));
+//        if (pad->direction == GST_PAD_SRC)
+          pad->pushfunc = gst_bin_pushfunc_wrapper;
+//        else
+          pad->pullfunc = gst_bin_pullfunc_wrapper;
+        pads = g_list_next(pads);
+      }
+      elements = g_list_next(elements);
+   }
+  } else {
+    g_print("BIN: don't need cothreads, looking for entry points\n");
+    // clear previous plan state
+    g_list_free(bin->entries);
+    bin->numentries = 0;
+    // we have to find which elements will drive an iteration
+    elements = bin->children;
+    while (elements) {
+      element = GST_ELEMENT(elements->data);
+      if (GST_IS_SRC(element)) {
+        g_print("adding '%s' as entry point\n",gst_element_get_name(element));
+        bin->entries = g_list_prepend(bin->entries,element);
+        bin->numentries++;
+      }
+      elements = g_list_next(elements);
+    }
+  }
 }
 
 void gst_bin_iterate_func(GstBin *bin) {
   GList *entries;
   GstElement *entry;
-   
+
+  g_print("gst_bin_iterate_func()\n");
+
   g_return_if_fail(bin != NULL);
   g_return_if_fail(GST_IS_BIN(bin));
-//  g_return_if_fail(GST_FLAG_IS_SET(thread,GST_STATE_RUNNING));
+  g_return_if_fail(GST_STATE(bin) == GST_STATE_PLAYING);
   g_return_if_fail(bin->numentries > 0);
-  
-  entries = bin->entries;  
 
   g_print("GstBin: iterating\n");
 
-  while (entries) {
-    entry = GST_ELEMENT(entries->data);
-    if (GST_IS_SRC(entry))
-      gst_src_push(GST_SRC(entry));
-    else if (GST_IS_CONNECTION(entry))
-      gst_connection_push(GST_CONNECTION(entry));
-    else
-      g_assert_not_reached();
-    entries = g_list_next(entries);
+  if (bin->need_cothreads) {
+    // all we really have to do is switch to the first child
+    // FIXME this should be lots more intelligent about where to start
+//  g_print("** in gst_bin_iterate_func()==================================%s\n",
+//          gst_element_get_name(GST_ELEMENT(bin->children->data)));
+    cothread_switch(GST_ELEMENT(bin->children->data)->threadstate);
+  } else {
+    entries = bin->entries;
+
+    while (entries) {
+      entry = GST_ELEMENT(entries->data);
+      if (GST_IS_SRC(entry))
+        gst_src_push(GST_SRC(entry));
+      else if (GST_IS_CONNECTION(entry))
+        gst_connection_push(GST_CONNECTION(entry));
+      else
+        g_assert_not_reached();
+      entries = g_list_next(entries);
+    }
   }
 //  g_print(",");
 }
index 7f534ef..8ba90d0 100644 (file)
@@ -52,9 +52,12 @@ typedef struct _GstBinClass GstBinClass;
 struct _GstBin {
   GstElement element;
 
+  // our children
   gint numchildren;
   GList *children;
 
+  // iteration state
+  gboolean need_cothreads;
   GList *entries;
   gint numentries;
 
index 1c795c8..9dcbe41 100644 (file)
@@ -105,7 +105,6 @@ void gst_clock_wait(GstClock *clock, GstClockTime time, GstObject *obj) {
   struct timeval tfnow;
   GstClockTime now;
   GstClockTimeDiff diff;
-  GList *elements;
 
   //DEBUG("gst_clock: requesting clock object 0x%p %08llu %08llu\n", obj, time, clock->current_time);
 
index 82e8a9e..7d0ef0b 100644 (file)
@@ -39,6 +39,9 @@ static void gst_element_class_init(GstElementClass *klass);
 static void gst_element_init(GstElement *element);
 static void gst_element_real_destroy(GtkObject *object);
 
+GstElementStateReturn gst_element_change_state(GstElement *element);
+
+
 static GstObjectClass *parent_class = NULL;
 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
 
@@ -92,15 +95,14 @@ static void gst_element_class_init(GstElementClass *klass) {
 
   gtk_object_class_add_signals(gtkobject_class,gst_element_signals,LAST_SIGNAL);
 
-  klass->start = NULL;
-  klass->stop = NULL;
   klass->change_state = gst_element_change_state;
 
   gtkobject_class->destroy = gst_element_real_destroy;
 }
 
 static void gst_element_init(GstElement *element) {
-  element->state = 0;
+  element->current_state = GST_STATE_NULL;
+  element->pending_state = -1;
   element->numpads = 0;
   element->pads = NULL;
   element->loopfunc = NULL;
@@ -282,37 +284,31 @@ void gst_element_error(GstElement *element,gchar *error) {
  *
  * Returns: whether or not the state was successfully set.
  */
-gboolean gst_element_set_state(GstElement *element,GstElementState state) {
+gint gst_element_set_state(GstElement *element,GstElementState state) {
   GstElementClass *oclass;
-  gboolean stateset = FALSE;
+  GstElementStateReturn return_val = GST_STATE_SUCCESS;
 
 //  g_print("gst_element_set_state(\"%s\",%08lx)\n",
 //          element->name,state);
 
-  g_return_val_if_fail(element != NULL, FALSE);
-  g_return_val_if_fail(GST_IS_ELEMENT(element), FALSE);
+  g_return_val_if_fail(element != NULL, GST_STATE_FAILURE);
+  g_return_val_if_fail(GST_IS_ELEMENT(element), GST_STATE_FAILURE);
 
-  oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
+  // first we set the pending state variable
+  // FIXME should probably check to see that we don't already have one
+  GST_STATE_PENDING(element) = state;
 
+  // now we call the state change function so it can set the state
+  oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
   if (oclass->change_state)
-    stateset = (oclass->change_state)(element,state);
+    return_val = (oclass->change_state)(element);
 
-  /* if a state *set* failed, unset it immediately */
-/*
-  if (!(state & GST_STATE_MAX) && !stateset) {
-    g_print("set state failed miserably, forcing unset\n");
-    if (oclass->change_state)
-      stateset = (oclass->change_state)(element,~state);
-    return FALSE;
-  }*/
-
-  return stateset;
+  return return_val;
 }
 
 /**
  * gst_element_change_state:
  * @element: element to change state of
- * @state: new element state
  *
  * Changes the state of the element, but more importantly fires off a signal
  * indicating the new state.  You can clear state by simply prefixing the
@@ -321,14 +317,14 @@ gboolean gst_element_set_state(GstElement *element,GstElementState state) {
  *
  * Returns: whether or not the state change was successfully set.
  */
-gboolean gst_element_change_state(GstElement *element,
-                                  GstElementState state) {
-  g_return_val_if_fail(element != NULL, FALSE);
-  g_return_val_if_fail(GST_IS_ELEMENT(element), FALSE);
+GstElementStateReturn gst_element_change_state(GstElement *element) {
+  g_return_val_if_fail(element != NULL, GST_STATE_FAILURE);
+  g_return_val_if_fail(GST_IS_ELEMENT(element), GST_STATE_FAILURE);
 
 //  g_print("gst_element_change_state(\"%s\",%d)\n",
 //          element->name,state);
 
+#ifdef OLDSTATE
   /* deal with the inverted state */
   //g_print("changing element state, was %08lx\n",GST_STATE(element));
   if (state & GST_STATE_MAX)
@@ -336,8 +332,12 @@ gboolean gst_element_change_state(GstElement *element,
   else
     GST_STATE_SET(element,state);
 //  g_print(", is now %08lx\n",GST_STATE(element));
+#else
+  GST_STATE(element) = GST_STATE_PENDING(element);
+  GST_STATE_PENDING(element) = GST_STATE_NONE_PENDING;
+#endif
   gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[STATE_CHANGE],
-                  state);
+                  GST_STATE(element));
   return TRUE;
 }
 
@@ -541,6 +541,7 @@ GstElement *gst_element_get_manager(GstElement *element) {
 int gst_element_loopfunc_wrapper(int argc,char **argv) {
   GstElement *element = GST_ELEMENT(argv);
   element->loopfunc(element);
+  return 0;
 }
 
 /**
index 966c33e..c8e0f7c 100644 (file)
@@ -35,6 +35,7 @@ extern "C" {
 #endif /* __cplusplus */
 
 
+#ifdef OLDSTATES
 typedef enum {
   GST_STATE_COMPLETE    = (1 << 0),
   GST_STATE_RUNNING     = (1 << 1),
@@ -47,17 +48,55 @@ typedef enum {
   GST_STATE_MAX                = (1 << 15),
 } GstElementState;
 
+typedef enum {
+  GST_STATE_FAILURE    = 0,
+  GST_STATE_SUCCESS    = 1,
+  GST_STATE_ASYNC      = 2,
+};
+#else
+typedef enum {
+  GST_STATE_NONE_PENDING       = -1,
+  GST_STATE_NULL       = 0,
+  GST_STATE_READY      = 1,
+  GST_STATE_PLAYING    = 2,
+  GST_STATE_PAUSED     = 3,
+} GstElementState;
+
+typedef enum {
+  GST_STATE_FAILURE    = 0,
+  GST_STATE_SUCCESS    = 1,
+  GST_STATE_ASYNC      = 2,
+} GstElementStateReturn;
+#endif
+
+static inline char *_gst_print_statename(int state) {
+  switch (state) {
+    case -1: return "none pending";break;
+    case 0: return "null";break;
+    case 1: return "ready";break;
+    case 2: return "playing";break;
+    case 3: return "paused";break;
+    default: return "";
+  }
+  return "";
+}
 
-#define GST_STATE(obj)                 (GST_ELEMENT(obj)->state)
+#define GST_STATE(obj)                 (GST_ELEMENT(obj)->current_state)
+#define GST_STATE_PENDING(obj)         (GST_ELEMENT(obj)->pending_state)
+
+#ifdef OLDSTATE
 #define GST_STATE_IS_SET(obj,flag)     (GST_STATE (obj) & (flag))
 #define GST_STATE_SET(obj,flag) \
 G_STMT_START{ (GST_STATE (obj) |= (flag)); \
-gst_info("GstElement: set '%s' state %d\n",gst_element_get_name(obj),flag); \
+gst_info("GstElement: set '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
+_gst_print_statename(flag)); \
 }G_STMT_END
 #define GST_STATE_UNSET(obj,flag) \
 G_STMT_START{ (GST_STATE (obj) &= ~(flag)); \
-gst_info("GstElement: unset '%s' state %d\n",gst_element_get_name(obj),flag); \
+gst_info("GstElement: unset '%s' state %d(%s)\n",gst_element_get_name(obj),flag, \
+_gst_print_statename(flag)); \
 }G_STMT_END
+#endif
 
 
 #define GST_TYPE_ELEMENT \
@@ -71,6 +110,13 @@ gst_info("GstElement: unset '%s' state %d\n",gst_element_get_name(obj),flag); \
 #define GST_IS_ELEMENT_CLASS(obj) \
   (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
 
+typedef enum {
+  GST_ELEMENT_MULTI_IN         = (1 << 16),
+} GstElementFlags;
+
+#define GST_ELEMENT_IS_MULTI_IN(obj)   (GST_FLAGS(obj) & GST_ELEMENT_MULTI_IN)
+
+
 typedef struct _GstElement GstElement;
 typedef struct _GstElementClass GstElementClass;
 typedef struct _GstElementDetails GstElementDetails;
@@ -83,7 +129,8 @@ struct _GstElement {
 
   gchar *name;
 
-  guint16 state;
+  guint8 current_state;
+  guint8 pending_state;
 
   GstElementLoopFunction loopfunc;
   cothread_state *threadstate;
@@ -107,11 +154,11 @@ struct _GstElementClass {
   void (*error) (GstElement *element,gchar *error);
 
   /* events */
-  gboolean (*start) (GstElement *element,GstElementState state);
-  gboolean (*stop) (GstElement *element);
+//  gboolean (*start) (GstElement *element,GstElementState state);
+//  gboolean (*stop) (GstElement *element);
 
   /* change the element state */
-  gboolean (*change_state) (GstElement *element,GstElementState state);
+  GstElementStateReturn (*change_state) (GstElement *element);
 
   /* create or read XML representation of self */
   xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent);
@@ -156,14 +203,10 @@ void gst_element_connect(GstElement *src,gchar *srcpadname,
                          GstElement *dest,gchar *destpadname);
 
 /* called by the app to set the state of the element */
-gboolean gst_element_set_state(GstElement *element,GstElementState state);
+gint gst_element_set_state(GstElement *element,GstElementState state);
 
 void gst_element_error(GstElement *element,gchar *error);
 
-/* callback to actually set the state */
-gboolean gst_element_change_state(GstElement *element,
-                                  GstElementState state);
-
 #define gst_element_destroy(element) gst_object_destroy(GST_OBJECT(element))
 
 /* XML write and read */
index 29f577a..d30c1d3 100644 (file)
@@ -80,9 +80,10 @@ static void gst_pad_init(GstPad *pad) {
   pad->type = 0;
   pad->direction = GST_PAD_UNKNOWN;
   pad->peer = NULL;
-  pad->chain = NULL;
-  pad->pull = NULL;
-  pad->qos = NULL;
+  pad->chainfunc = NULL;
+  pad->pullfunc = NULL;
+  pad->pushfunc = NULL;
+  pad->qosfunc = NULL;
   pad->parent = NULL;
   pad->ghostparents = NULL;
 }
@@ -158,35 +159,60 @@ gchar *gst_pad_get_name(GstPad *pad) {
 void gst_pad_set_pull_function(GstPad *pad,GstPadPullFunction pull) {
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
-  
-  pad->pull = pull;
+
+  fprintf(stderr, "pad setting pull function\n");
+
+  pad->pullfunc = pull;
 }
 
 void gst_pad_set_chain_function(GstPad *pad,GstPadChainFunction chain) {
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
   
-  pad->chain = chain;
+  pad->chainfunc = chain;
 }
 
 void gst_pad_set_qos_function(GstPad *pad,GstPadQoSFunction qos) {
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
   
-  pad->qos = qos;
+  pad->qosfunc = qos;
 }
 
+/* gst_pad_push is handed the src pad and the buffer to push */
 void gst_pad_push(GstPad *pad,GstBuffer *buffer) {
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
-  g_return_if_fail(GST_PAD_CONNECTED(pad));
+//  g_return_if_fail(GST_PAD_CONNECTED(pad));
   g_return_if_fail(buffer != NULL);
 
   gst_trace_add_entry(NULL,0,buffer,"push buffer");
+
+  // FIXME we should probably make some noise here...
+  if (!GST_PAD_CONNECTED(pad)) return;
+
+//  g_return_if_fail(pad->pushfunc != NULL);
+
+  // first check to see if there's a push handler
+  if (pad->pushfunc != NULL) {
+//    g_print("-- gst_pad_push(): putting buffer in pen and calling push handler\n");
+    // put the buffer in peer's holding pen
+    pad->peer->bufpen = buffer;
+    // now inform the handler that the peer pad has something
+    (pad->pushfunc)(pad->peer);
+  // otherwise we assume we're chaining directly
+  } else if (pad->chainfunc != NULL) {
+    (pad->chainfunc)(pad->peer,buffer);
+  // else we squawk
+  } else {
+//    g_print("-- gst_pad_push(): houston, we have a problem, no way of talking to peer\n");
+  }
+
+#ifdef OLD_STUFF
   // if the chain function exists for the pad, call it directly
   if (pad->chain)
     (pad->chain)(pad->peer,buffer);
-  // else we're likely going to have to coroutine it
+  // else we're likely going to have to cothread it
   else {
     pad->peer->bufpen = buffer;
     g_print("GstPad: would switch to a coroutine here...\n");
@@ -195,22 +221,51 @@ void gst_pad_push(GstPad *pad,GstBuffer *buffer) {
     if (GST_ELEMENT(pad->peer->parent)->threadstate != NULL)
       cothread_switch(GST_ELEMENT(pad->peer->parent)->threadstate);
   }
+#endif
 }
 
+/* gst_pad_pull() is given the sink pad */
 GstBuffer *gst_pad_pull(GstPad *pad) {
   GstBuffer *buf;
-  GstElement *peerparent;
-  cothread_state *state;
+//  GstElement *peerparent;
+//  cothread_state *state;
 
   g_return_val_if_fail(pad != NULL, NULL);
   g_return_val_if_fail(GST_IS_PAD(pad), NULL);
 
+//  g_print("-- gst_pad_pull(): attempting to pull buffer\n");
+
+//  g_return_val_if_fail(pad->pullfunc != NULL, NULL);
+
+  // if no buffer in pen and there's a pull handler, fire it
+  if (pad->bufpen == NULL) {
+    if (pad->pullfunc != NULL) {
+//      g_print("-- gst_pad_pull(): calling pull handler\n");
+      (pad->pullfunc)(pad->peer);
+    } else {
+//      g_print("-- gst_pad_pull(): no buffer in pen, and no handler to get one there!!!\n");
+    }
+  }
+
+  // if there's a buffer in the holding pen, use it
+  if (pad->bufpen != NULL) {
+//    g_print("-- gst_pad_pull(): buffer available, pulling\n");
+    buf = pad->bufpen;
+    pad->bufpen = NULL;
+    return buf;
+  // else we have a big problem...
+  } else {
+//    g_print("-- gst_pad_pull(): uh, nothing in pen and no handler\n");
+    return NULL;
+  }
+
+#ifdef OLD_STUFF
   // if the pull function exists for the pad, call it directly
   if (pad->pull) {
     return (pad->pull)(pad->peer);
-  // else we're likely going to have to coroutine it
+  // else we're likely going to have to cothread it
   } else if (pad->bufpen == NULL) {
-    g_print("GstPad: no buffer available, will have to do something about it\n");
+    g_print("no buffer available, will have to do something about it\n");
     peerparent = GST_ELEMENT(pad->peer->parent);
     // if they're a cothread too, we can just switch to them
     if (peerparent->threadstate != NULL) {
@@ -227,19 +282,22 @@ GstBuffer *gst_pad_pull(GstPad *pad) {
     pad->bufpen = NULL;
     return buf;
   }
-       return NULL;
+#endif
+
+  return NULL;
 }
 
 void gst_pad_chain(GstPad *pad) {
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
   g_return_if_fail(pad->peer != NULL);
-  g_return_if_fail(pad->chain != NULL);
+  g_return_if_fail(pad->chainfunc != NULL);
 
-  if (pad->bufpen)
-    (pad->chain)(pad,pad->bufpen);
+  if (pad->bufpen && pad->chainfunc)
+    (pad->chainfunc)(pad,pad->bufpen);
 }
 
+
 /**
  * gst_pad_handle_qos:
  * @element: element to change state of
@@ -255,8 +313,8 @@ void gst_pad_handle_qos(GstPad *pad,
 
   DEBUG("gst_pad_handle_qos(\"%s\",%08ld)\n", GST_ELEMENT(pad->parent)->name,qos_message);
 
-  if (pad->qos) {
-    (pad->qos)(pad,qos_message);
+  if (pad->qosfunc) {
+    (pad->qosfunc)(pad,qos_message);
   }
   else {
     element = GST_ELEMENT(pad->peer->parent);
@@ -292,9 +350,8 @@ void gst_pad_disconnect(GstPad *srcpad,GstPad *sinkpad) {
   srcpad->peer = NULL;
   sinkpad->peer = NULL;
 
-  srcpad->chain = NULL;
-  srcpad->pull = NULL;
-
+  srcpad->chainfunc = NULL;
+  srcpad->pullfunc = NULL;
 }
 
 void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad) {
@@ -324,9 +381,9 @@ void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad) {
   sinkpad->peer = srcpad;
 
   /* now copy the chain pointer from sink to src */
-  srcpad->chain = sinkpad->chain;
+  srcpad->chainfunc = sinkpad->chainfunc;
   /* and the pull function */
-  srcpad->pull = sinkpad->pull;
+  srcpad->pullfunc = sinkpad->pullfunc;
 
   /* set the connected flag */
   /* FIXME: set connected flag */
index 10879c1..9e2083e 100644 (file)
@@ -39,10 +39,8 @@ extern "C" {
 #define GST_IS_PAD_CLASS(obj)        (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PAD))
 
 // quick test to see if the pad is connected
-#define GST_PAD_CONNECTED(pad) \
-       ((pad)->peer != NULL)
-#define GST_PAD_CAN_PULL(pad) \
-       ((pad)->pull != NULL)
+#define GST_PAD_CONNECTED(pad) ((pad)->peer != NULL)
+#define GST_PAD_CAN_PULL(pad) ((pad)->pullfunc != NULL)
 
 typedef struct _GstPad GstPad;
 typedef struct _GstPadClass GstPadClass;
@@ -51,7 +49,7 @@ typedef struct _GstPadClass GstPadClass;
  * pad is the sink pad (so the same chain function can be used for N pads)
  * buf is the buffer being passed */
 typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
-typedef GstBuffer *(*GstPadPullFunction) (GstPad *pad);
+typedef void (*GstPadPullFunction) (GstPad *pad);
 typedef void (*GstPadPushFunction) (GstPad *pad);
 typedef void (*GstPadQoSFunction) (GstPad *pad, glong qos_message);
 
@@ -76,9 +74,10 @@ struct _GstPad {
 
   GstBuffer *bufpen;
 
-  GstPadChainFunction chain;
-  GstPadPullFunction pull;
-  GstPadQoSFunction qos;
+  GstPadChainFunction chainfunc;
+  GstPadPullFunction pullfunc;
+  GstPadPushFunction pushfunc;
+  GstPadQoSFunction qosfunc;
 
   GstObject *parent;
   GList *ghostparents;
index edcbea9..6e9677d 100644 (file)
@@ -44,8 +44,7 @@ enum {
 static void gst_pipeline_class_init(GstPipelineClass *klass);
 static void gst_pipeline_init(GstPipeline *pipeline);
 
-static gboolean gst_pipeline_change_state(GstElement *element,
-                                          GstElementState state);
+static GstElementStateReturn gst_pipeline_change_state(GstElement *element);
 
 static void gst_pipeline_prepare(GstPipeline *pipeline);
 
@@ -109,31 +108,33 @@ static void gst_pipeline_prepare(GstPipeline *pipeline) {
 }
 
 
-static gboolean gst_pipeline_change_state(GstElement *element,
-                                          GstElementState state) {
+static GstElementStateReturn gst_pipeline_change_state(GstElement *element) {
   GstPipeline *pipeline;
 
+/*
   g_return_val_if_fail(GST_IS_PIPELINE(element), FALSE);
   pipeline = GST_PIPELINE(element);
 
   switch (state) {
-    case GST_STATE_RUNNING:
-      /* we need to set up internal state */
-      g_print("GstPipeline: preparing pipeline \"%s\" for iterations:\n",
+    case GST_STATE_READY:
+      // we need to set up internal state
+      g_print("preparing pipeline \"%s\" for iterations:\n",
               gst_element_get_name(GST_ELEMENT(element)));
       gst_pipeline_prepare(pipeline);
       break;
+#if OLDSTATE
     case ~GST_STATE_RUNNING:
-      /* tear down the internal state */
-      g_print("GstPipeline: tearing down pipelines's \"%s\" iteration state\n",
-              gst_element_get_name(GST_ELEMENT(element)));
+      // tear down the internal state
+      g_print("tearing down pipelines's iteration state\n");
       break;
+#endif
     default:
       break;
   }
     
   if (GST_ELEMENT_CLASS(parent_class)->change_state)
     return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
+*/
   return TRUE;
 }
 
index 89ff676..3141647 100644 (file)
@@ -47,8 +47,7 @@ static void gst_thread_init(GstThread *thread);
 
 static void gst_thread_set_arg(GtkObject *object,GtkArg *arg,guint id);
 static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id);
-static gboolean gst_thread_change_state(GstElement *element,
-                                        GstElementState state);
+static GstElementStateReturn gst_thread_change_state(GstElement *element);
 
 static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent);
 
@@ -104,8 +103,8 @@ gst_thread_class_init(GstThreadClass *klass) {
 static void gst_thread_init(GstThread *thread) {
   GST_FLAG_SET(thread,GST_THREAD_CREATE);
 
-  thread->entries = NULL;
-  thread->numentries = 0;
+//  thread->entries = NULL;
+//  thread->numentries = 0;
 
   thread->lock = g_mutex_new();
   thread->cond = g_cond_new();
@@ -145,6 +144,7 @@ static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id) {
   }
 }
 
+
 /**
  * gst_thread_new:
  * @name: the name of the thread
@@ -162,6 +162,7 @@ GstElement *gst_thread_new(guchar *name) {
 }
 
 
+#ifdef OLD_STUFF
 static void gst_thread_prepare(GstThread *thread) {
   GList *elements;
   GstElement *element;
@@ -211,13 +212,14 @@ for internal element \"%s\"\n",
   }
   gst_info("gstthread: have %d entries into thread\n",thread->numentries);
 }
+#endif
 
 
-static gboolean gst_thread_change_state(GstElement *element,
-                                        GstElementState state) {
+static GstElementStateReturn gst_thread_change_state(GstElement *element) {
   GstThread *thread;
   gboolean stateset = TRUE;
 
+/*
   g_return_val_if_fail(GST_IS_THREAD(element), FALSE);
   thread = GST_THREAD(element);
 
@@ -225,18 +227,19 @@ static gboolean gst_thread_change_state(GstElement *element,
     stateset = GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
 
   switch (state) {
-    case GST_STATE_RUNNING:
+    case GST_STATE_READY:
       if (!stateset) return FALSE;
-      /* we want to prepare our internal state for doing the iterations */
-      gst_info("gstthread: preparing thread \"%s\" for iterations:\n",
+      // we want to prepare our internal state for doing the iterations
+      gst_info("preparing thread \"%s\" for iterations:\n",
                gst_element_get_name(GST_ELEMENT(element)));
-      gst_thread_prepare(thread);
-      if (thread->numentries == 0)
-        return FALSE;
-      /* set the state to idle */
+//      gst_thread_prepare(thread);
+      gst_bin_create_plan(GST_BIN(thread));
+//      if (thread->numentries == 0)
+//        return FALSE;
+      // set the state to idle
       GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
-      /* create the thread if that's what we're supposed to do */
-      gst_info("gstthread: flags are 0x%08x\n",GST_FLAGS(thread));
+      // create the thread if that's what we're supposed to do
+      gst_info("flags are 0x%08x\n",GST_FLAGS(thread));
       if (GST_FLAG_IS_SET(thread,GST_THREAD_CREATE)) {
         gst_info("gstthread: starting thread \"%s\"\n",
                  gst_element_get_name(GST_ELEMENT(element)));
@@ -248,17 +251,18 @@ static gboolean gst_thread_change_state(GstElement *element,
       }
       return TRUE;
       break;
+#if OLDSTATE
     case ~GST_STATE_RUNNING:
-      /* stop, reap, and join the thread */
+      // stop, reap, and join the thread
       GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
       GST_FLAG_SET(thread,GST_THREAD_STATE_REAPING);
       gst_thread_signal_thread(thread);
-      //pthread_join(thread->thread_id,0);
-      /* tear down the internal state */
-      gst_info("gstthread: tearing down thread's \"%s\" iteration state\n",
-                     gst_element_get_name(GST_ELEMENT(element)));
-      /* FIXME do stuff */
+      pthread_join(thread->thread_id,0);
+      // tear down the internal state
+      gst_info("tearing down thread's iteration state\n");
+      // FIXME do stuff
       break;
+#endif
     case GST_STATE_PLAYING:
       if (!stateset) return FALSE;
       gst_info("gstthread: starting thread \"%s\"\n",
@@ -276,6 +280,7 @@ static gboolean gst_thread_change_state(GstElement *element,
     default:
       break;
   }
+*/
 
   return stateset;
 }
@@ -295,7 +300,7 @@ void *gst_thread_main_loop(void *arg) {
 
   while(!GST_FLAG_IS_SET(thread,GST_THREAD_STATE_REAPING)) {
     if (GST_FLAG_IS_SET(thread,GST_THREAD_STATE_SPINNING))
-      gst_thread_iterate(thread);
+      gst_bin_iterate(GST_BIN(thread));
     else {
       g_mutex_lock(thread->lock);
       g_cond_wait(thread->cond,thread->lock);
@@ -311,6 +316,7 @@ void *gst_thread_main_loop(void *arg) {
   return NULL;
 }
 
+#ifdef OLD_STUFF
 /**
  * gst_thread_iterate:
  * @thread: the thread to iterate
@@ -343,6 +349,7 @@ void gst_thread_iterate(GstThread *thread) {
   DEBUG("gstthread: %s: thread iterate done\n", gst_element_get_name(GST_ELEMENT(thread)));
   //g_print(",");
 }
+#endif
 
 static void gst_thread_signal_thread(GstThread *thread) {
   g_mutex_lock(thread->lock);
index fffd6f5..0f96eb0 100644 (file)
@@ -57,9 +57,6 @@ typedef struct _GstThreadClass GstThreadClass;
 struct _GstThread {
   GstBin bin;
 
-  GList *entries;              /* used to determine iterate behavior */
-  gint numentries;             /* number of above entry points */
-
   pthread_t thread_id;         /* id of the thread, if any */
   GMutex *lock;                        /* thread lock/condititon pair... */
   GCond *cond;                 /* used to control the thread */
index 1d8fc43..e7464e3 100644 (file)
@@ -45,13 +45,13 @@ struct _elements_entry {
 };
 
 struct _elements_entry _elements[] = {
+  { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
+  { "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
   { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details },
   { "audiosink", gst_audiosink_get_type, &gst_audiosink_details },
   { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details },
   { "disksrc", gst_disksrc_get_type, &gst_disksrc_details },
   { "identity", gst_identity_get_type, &gst_identity_details },
-  { "fakesink", gst_fakesink_get_type, &gst_fakesink_details },
-  { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details },
   { "fdsink", gst_fdsink_get_type, &gst_fdsink_details },
   { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details },
 #if HAVE_LIBGHTTP
index 4b97c4a..7d00e60 100644 (file)
@@ -86,8 +86,8 @@ static void gst_fakesink_init(GstFakeSink *fakesink) {
   gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad);
   gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain);
 
-  // we're already complete, since we don't have any args...
-  gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE);
+  // we're ready right away, since we don't have any args...
+//  gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_READY);
 }
 
 /**
@@ -120,8 +120,8 @@ void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) {
   g_return_if_fail(buf != NULL);
 
   fakesink = GST_FAKESINK(pad->parent);
-//  g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n",
-//          buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink)));
+//  g_print("gst_fakesink_chain: got buffer in '%s'\n",
+//          gst_element_get_name(GST_ELEMENT(fakesink)));
   g_print("<");
   gst_buffer_unref(buf);
 }
index 565caa2..495f180 100644 (file)
@@ -87,8 +87,8 @@ static void gst_fakesrc_init(GstFakeSrc *fakesrc) {
   fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
   gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad);
 
-  // we're already complete, since we don't have any args...
-  gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE);
+  // we're ready right away, since we don't have any args...
+//  gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
 }
 
 /**
index 794e22e..d24efa9 100644 (file)
@@ -3,15 +3,15 @@
 extern gboolean _gst_plugin_spew;
 
 int main(int argc,char *argv[]) {
-  GstPipeline *pipeline;
+  GstBin *bin;
   GstElement *src, *sink;
   GstPad *srcpad, *sinkpad;
 
 //  _gst_plugin_spew = TRUE;
   gst_init(&argc,&argv);
 
-  pipeline = gst_pipeline_new("pipeline");
-  g_return_if_fail(pipeline != NULL);
+  bin = gst_bin_new("bin");
+  g_return_if_fail(bin != NULL);
 
   g_print("--- creating src and sink elements\n");
   src = gst_elementfactory_make("fakesrc","src");
@@ -19,9 +19,9 @@ int main(int argc,char *argv[]) {
   sink = gst_elementfactory_make("fakesink","sink");
   g_return_if_fail(sink != NULL);
 
-  g_print("--- about to add the elements to the pipeline\n");
-  gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(src));
-  gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(sink));
+  g_print("--- about to add the elements to the bin\n");
+  gst_bin_add(bin,GST_ELEMENT(src));
+  gst_bin_add(bin,GST_ELEMENT(sink));
 
   g_print("--- getting pads\n");
   srcpad = gst_element_get_pad(src,"src");
@@ -33,5 +33,10 @@ int main(int argc,char *argv[]) {
   gst_pad_connect(srcpad,sinkpad);
 
   g_print("--- setting up\n");
-  gst_pipeline_iterate(pipeline);
+  gst_element_set_state(GST_ELEMENT(bin),GST_STATE_READY);
+
+  g_print("--- creating plan\n");
+  gst_bin_create_plan(bin);
+  g_print("--- iterating\n");
+  gst_bin_iterate(bin);
 }
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644 (file)
index 0000000..abd7e96
--- /dev/null
@@ -0,0 +1,12 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+init
+loadall
+simplefake
+states
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..e640909
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_PROGRAMS = init loadall simplefake states
+
+LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_builddir)/gst/libgst.la
+
+INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir)
+
+EXTRA_DIST = README
diff --git a/tests/README b/tests/README
new file mode 100644 (file)
index 0000000..274b291
--- /dev/null
@@ -0,0 +1,2 @@
+This directory contains various tests designed to verify GStreamer
+behavior.  If any of them exit with a non-zero value, something's wrong.
diff --git a/tests/init.c b/tests/init.c
new file mode 100644 (file)
index 0000000..a66c5e5
--- /dev/null
@@ -0,0 +1,5 @@
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) {
+  gst_init(&argc,&argv);
+}
diff --git a/tests/loadall.c b/tests/loadall.c
new file mode 100644 (file)
index 0000000..c663bf9
--- /dev/null
@@ -0,0 +1,6 @@
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) {
+  gst_init(&argc,&argv);
+  gst_plugin_load_all();
+}
diff --git a/tests/simplefake.c b/tests/simplefake.c
new file mode 100644 (file)
index 0000000..079f533
--- /dev/null
@@ -0,0 +1,17 @@
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) {
+  GstPipeline *pipeline;
+  GstElement *src,*sink;
+
+  gst_init(&argc,&argv);
+
+  pipeline = gst_pipeline_new("fakepipeline");
+  src = gst_elementfactory_make("fakesrc","fakesrc");
+  g_return_val_if_fail(1,src != NULL);
+  sink = gst_elementfactory_make("fakesink","fakesink");
+  g_return_val_if_fail(1,sink != NULL);
+
+  gst_bin_add(GST_BIN(pipeline),src);
+  gst_bin_add(GST_BIN(pipeline),sink);
+}
diff --git a/tests/states.c b/tests/states.c
new file mode 100644 (file)
index 0000000..baafa21
--- /dev/null
@@ -0,0 +1,46 @@
+#include <gst/gst.h>
+
+gboolean state_change(GstElement *element,GstElementState state) {
+  g_print("state_change: element '%s' state set to %d(%s)\n",
+       gst_element_get_name(element),state,_gst_print_statename(state));
+  g_print("state_change: element state is actually %d\n",GST_STATE(element));
+}
+
+int main(int argc,char *argv[]) {
+  GstElement *bin;
+  GstElement *src,*sink;
+
+  gst_init(&argc,&argv);
+
+  src = gst_elementfactory_make("fakesrc","src");
+  g_return_val_if_fail(1,src != NULL);
+  sink = gst_elementfactory_make("fakesink","sink");
+  g_return_val_if_fail(1,sink != NULL);
+  bin = gst_bin_new("bin");
+  g_return_val_if_fail(1,bin != NULL);
+
+  gtk_signal_connect(GTK_OBJECT(src),"state_change",
+                     GTK_SIGNAL_FUNC(state_change),NULL);
+  gtk_signal_connect(GTK_OBJECT(sink),"state_change",
+                     GTK_SIGNAL_FUNC(state_change),NULL);
+  gtk_signal_connect(GTK_OBJECT(bin),"state_change",
+                     GTK_SIGNAL_FUNC(state_change),NULL);
+
+  g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(src),
+       GST_STATE(src),_gst_print_statename(GST_STATE(src)));
+  g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(sink),
+       GST_STATE(sink),_gst_print_statename(GST_STATE(sink)));
+  g_print("element '%s' starts at state %d(%s)\n",gst_element_get_name(bin),
+       GST_STATE(bin),_gst_print_statename(GST_STATE(bin)));
+
+  gst_bin_add(GST_BIN(bin),src);
+  gst_bin_add(GST_BIN(bin),sink);
+
+  gst_pad_connect(gst_element_get_pad(src,"src"),
+                  gst_element_get_pad(sink,"sink"));
+
+  gst_bin_create_plan(bin);
+  gst_element_set_state(bin,GST_STATE_PLAYING);
+
+  gst_bin_iterate(bin);
+}