-SUBDIRS = gst plugins test editor tools docs libs
+SUBDIRS = gst libs plugins test editor tools docs tests
bin_SCRIPTS = gstreamer-config
popd > /dev/null
done
-./configure --enable-maintainer-mode "$@"
+./configure --enable-maintainer-mode --enable-debug "$@"
echo
echo "Now type 'make' to compile $package."
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)
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
SUBDIRS =
if HAVE_GTK_DOC
- SUBDIRS += gst
+ SUBDIRS += gst manual
endif
-DIST_SUBDIRS = gst
+DIST_SUBDIRS = gst manual
EXTRA_DIST = random slides
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>
<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 \
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>
<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>
#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>
};
</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 */
GstElement element;
};
</STRUCT>
-<STRUCT>
-<NAME>GstFilterClass</NAME>
-struct GstFilterClass {
- GstElementClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_filter_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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)
</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>
</USER_FUNCTION>
<USER_FUNCTION>
<NAME>GstPadPullFunction</NAME>
-<RETURNS>GstBuffer *</RETURNS>
+<RETURNS>void </RETURNS>
GstPad *pad
</USER_FUNCTION>
<USER_FUNCTION>
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>
GstBin bin;
};
</STRUCT>
-<STRUCT>
-<NAME>GstPipelineClass</NAME>
-struct GstPipelineClass {
- GstBinClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_pipeline_get_type</NAME>
<RETURNS>GtkType </RETURNS>
GstElement element;
};
</STRUCT>
-<STRUCT>
-<NAME>GstSinkClass</NAME>
-struct GstSinkClass {
- GstElementClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_sink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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) \
GSList *srcpads;
};
</STRUCT>
-<STRUCT>
-<NAME>GstTeeClass</NAME>
-struct GstTeeClass {
- GstFilterClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_tee_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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>
<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 \
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>
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>
MetaAudioRaw *meta;
};
</STRUCT>
-<STRUCT>
-<NAME>GstAudioSrcClass</NAME>
-struct GstAudioSrcClass {
- GstSrcClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_audiosrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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>
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>
GstPad *sinkpad;
};
</STRUCT>
-<STRUCT>
-<NAME>GstFakeSinkClass</NAME>
-struct GstFakeSinkClass {
- GstSinkClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_fakesink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
GstPad *srcpad;
};
</STRUCT>
-<STRUCT>
-<NAME>GstFakeSrcClass</NAME>
-struct GstFakeSrcClass {
- GstSrcClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_fakesrc_get_type</NAME>
<RETURNS>GtkType </RETURNS>
int fd;
};
</STRUCT>
-<STRUCT>
-<NAME>GstFdSinkClass</NAME>
-struct GstFdSinkClass {
- GstSinkClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_fdsink_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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>
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>
gint control;
};
</STRUCT>
-<STRUCT>
-<NAME>GstIdentityClass</NAME>
-struct GstIdentityClass {
- GstFilterClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_identity_get_type</NAME>
<RETURNS>GtkType </RETURNS>
GCond *fullcond;
};
</STRUCT>
-<STRUCT>
-<NAME>GstQueueClass</NAME>
-struct GstQueueClass {
- GstConnectionClass parent_class;
-};
-</STRUCT>
<FUNCTION>
<NAME>gst_queue_get_type</NAME>
<RETURNS>GtkType </RETURNS>
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>
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)
};
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
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);
}
/**
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);
}
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);
}
/**
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);
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.
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,
oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass);
+g_print("gst_bin_iterate()\n");
if (oclass->iterate)
(oclass->iterate)(bin);
}
(oclass->create_plan)(bin);
}
+#ifdef OLD_STUFF
static void gst_bin_create_plan_func(GstBin *bin) {
GList *elements;
GstElement *element;
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");
}
}
- /* 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);
}
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(",");
}
struct _GstBin {
GstElement element;
+ // our children
gint numchildren;
GList *children;
+ // iteration state
+ gboolean need_cothreads;
GList *entries;
gint numentries;
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);
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 };
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;
*
* 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
*
* 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)
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;
}
int gst_element_loopfunc_wrapper(int argc,char **argv) {
GstElement *element = GST_ELEMENT(argv);
element->loopfunc(element);
+ return 0;
}
/**
#endif /* __cplusplus */
+#ifdef OLDSTATES
typedef enum {
GST_STATE_COMPLETE = (1 << 0),
GST_STATE_RUNNING = (1 << 1),
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 \
#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;
gchar *name;
- guint16 state;
+ guint8 current_state;
+ guint8 pending_state;
GstElementLoopFunction loopfunc;
cothread_state *threadstate;
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);
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 */
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;
}
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");
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) {
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
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);
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) {
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 */
#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;
* 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);
GstBuffer *bufpen;
- GstPadChainFunction chain;
- GstPadPullFunction pull;
- GstPadQoSFunction qos;
+ GstPadChainFunction chainfunc;
+ GstPadPullFunction pullfunc;
+ GstPadPushFunction pushfunc;
+ GstPadQoSFunction qosfunc;
GstObject *parent;
GList *ghostparents;
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);
}
-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;
}
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);
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();
}
}
+
/**
* gst_thread_new:
* @name: the name of the thread
}
+#ifdef OLD_STUFF
static void gst_thread_prepare(GstThread *thread) {
GList *elements;
GstElement *element;
}
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);
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)));
}
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",
default:
break;
}
+*/
return stateset;
}
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);
return NULL;
}
+#ifdef OLD_STUFF
/**
* gst_thread_iterate:
* @thread: the thread to iterate
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);
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 _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
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);
}
/**
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);
}
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);
}
/**
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");
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");
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);
}
--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+init
+loadall
+simplefake
+states
--- /dev/null
+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
--- /dev/null
+This directory contains various tests designed to verify GStreamer
+behavior. If any of them exit with a non-zero value, something's wrong.
--- /dev/null
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) {
+ gst_init(&argc,&argv);
+}
--- /dev/null
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) {
+ gst_init(&argc,&argv);
+ gst_plugin_load_all();
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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);
+}