diff --git a/ChangeLog b/ChangeLog index 6534581938..5bf7d28b6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2005-10-28 Wim Taymans + + * docs/design/part-TODO.txt: + Add an item to TODO. + + * gst/gstiterator.c: (gst_iterator_fold), + (gst_iterator_find_custom): + * gst/gstiterator.h: + Add iterator docs. + 2005-10-28 Wim Taymans * gst/base/gstbasetransform.c: (gst_base_transform_class_init), diff --git a/docs/design/part-TODO.txt b/docs/design/part-TODO.txt index 599bb0851a..fa82fb2793 100644 --- a/docs/design/part-TODO.txt +++ b/docs/design/part-TODO.txt @@ -20,6 +20,8 @@ in the sinks. This sample should be discarded, possibly with a flush event started from the source. +- convert framerate to GstFraction in GstCaps. + - implement latency calculation for live sources. - implement master/slave clocks. diff --git a/gst/gstiterator.c b/gst/gstiterator.c index 62359b6c44..d3ea25294f 100644 --- a/gst/gstiterator.c +++ b/gst/gstiterator.c @@ -30,6 +30,32 @@ * * Various GStreamer objects provide access to their internal structures using * an iterator. + * + * The basic use pattern of an iterator is as follows: + * + * + * Using an iterator + * + * it = _get_iterator(object); + * done = FALSE; + * while (!done) { + * switch (gst_iterator_next (it, &item)) { + * case GST_ITERATOR_OK: + * ... use/change item here... + * gst_object_unref (item); + * break; + * case GST_ITERATOR_RESYNC: + * ...rollback changes to items... + * gst_iterator_resync (it); + * break; + * case GST_ITERATOR_DONE: + * done = TRUE; + * break; + * } + * } + * gst_iterator_free (it); + * + * */ #include "gst_private.h" @@ -464,7 +490,7 @@ gst_iterator_fold (GstIterator * iter, GstIteratorFoldFunction func, result = gst_iterator_next (iter, &item); switch (result) { case GST_ITERATOR_OK: - /* fixme: is there a way to ref/unref items? */ + /* FIXME: is there a way to ref/unref items? */ if (!func (item, ret, user_data)) goto fold_done; else @@ -548,6 +574,9 @@ find_custom_fold_func (gpointer item, GValue * ret, FindCustomFoldData * data) * * The iterator will not be freed. * + * This function will return NULL if an error or resync happened to + * the iterator. + * * Returns: The element in the iterator that matches the compare * function or NULL when no element matched. * @@ -565,6 +594,8 @@ gst_iterator_find_custom (GstIterator * iter, GCompareFunc func, data.func = func; data.user_data = user_data; + /* FIXME, we totally ignore RESYNC and return NULL so that the + * app does not know if the element was not found or a resync happened */ res = gst_iterator_fold (iter, (GstIteratorFoldFunction) find_custom_fold_func, &ret, &data); diff --git a/gst/gstiterator.h b/gst/gstiterator.h index 4e9a1ec0ab..6170ed6870 100644 --- a/gst/gstiterator.h +++ b/gst/gstiterator.h @@ -27,36 +27,170 @@ G_BEGIN_DECLS +/** + * GstIteratorResult: + * @GST_ITERATOR_DONE: No more items in the iterator + * @GST_ITERATOR_OK: An item was retrieved + * @GST_ITERATOR_RESYNC: Datastructure changed while iterating + * @GST_ITERATOR_ERROR: An error happened + * + * The result of gst_iterator_next(). + */ typedef enum { - GST_ITERATOR_DONE = 0, /* no more items in the iterator */ - GST_ITERATOR_OK = 1, /* item retrieved */ - GST_ITERATOR_RESYNC = 2, /* datastructures changed while iterating */ - GST_ITERATOR_ERROR = 3, /* some error happened */ + GST_ITERATOR_DONE = 0, + GST_ITERATOR_OK = 1, + GST_ITERATOR_RESYNC = 2, + GST_ITERATOR_ERROR = 3, } GstIteratorResult; typedef struct _GstIterator GstIterator; +/** + * GstIteratorItem: + * @GST_ITERATOR_ITEM_SKIP: Skip this item + * @GST_ITERATOR_ITEM_PASS: Return item + * @GST_ITERATOR_ITEM_END: Stop after this item. + * + * The result of a GstIteratorItemFunction. + */ typedef enum { - GST_ITERATOR_ITEM_SKIP = 0, /* skip item */ - GST_ITERATOR_ITEM_PASS = 1, /* return item */ - GST_ITERATOR_ITEM_END = 2, /* stop after this item */ + GST_ITERATOR_ITEM_SKIP = 0, + GST_ITERATOR_ITEM_PASS = 1, + GST_ITERATOR_ITEM_END = 2, } GstIteratorItem; +/** + * GstIteratorDisposeFunction: + * @owner: the owner of the iterator + * + * The function that will be called when a GList iterator is freed. The + * owner of the GList iterator can then clean up its resources. + */ typedef void (*GstIteratorDisposeFunction) (gpointer owner); +/** + * GstIteratorNextFunction: + * @it: the iterator + * @result: a pointer to hold the next item + * + * The function that will be called when the next element of the iterator + * should be retrieved. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + * + * Returns: the result of the operation. + */ typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, gpointer *result); +/** + * GstIteratorItemFunction: + * @it: the iterator + * @item: the item being retrieved. + * + * The function that will be called after the next item of the iterator + * has been retrieved. This function will typically increase the refcount + * of the item or make a copy. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + * + * Returns: the result of the operation. + */ typedef GstIteratorItem (*GstIteratorItemFunction) (GstIterator *it, gpointer item); +/** + * GstIteratorResyncFunction: + * @it: the iterator + * + * This function will be called whenever a concurrent update happened + * to the iterated datastructure. The implementor of the iterator should + * restart the iterator from the beginning and clean up any state it might + * have. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + */ typedef void (*GstIteratorResyncFunction) (GstIterator *it); +/** + * GstIteratorFreeFunction: + * @it: the iterator + * + * This function will be called when the iterator is freed. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + */ typedef void (*GstIteratorFreeFunction) (GstIterator *it); +/** + * GstIteratorFoldFunction: + * @item: the item to fold + * @ret: a GValue collecting the result + * @user_data: data passed to #gst_iterator_fold + * + * A function to be passed to #gst_iterator_fold. + * + * Returns: TRUE if the fold should continue, FALSE if it should stop. + */ typedef gboolean (*GstIteratorFoldFunction) (gpointer item, GValue *ret, gpointer user_data); +/** + * GST_ITERATOR: + * @it: the #GstIterator value + * + * Macro to cast to a #GstIterator + */ #define GST_ITERATOR(it) ((GstIterator*)(it)) +/** + * GST_ITERATOR_LOCK: + * @it: the #GstIterator to get the lock of + * + * Macro to get the lock protecting the datastructure being iterated. + */ #define GST_ITERATOR_LOCK(it) (GST_ITERATOR(it)->lock) +/** + * GST_ITERATOR_COOKIE: + * @it: the #GstIterator to get the cookie of + * + * Macro to get the cookie of a #GstIterator. The cookie of the + * iterator is the value of the master cookie when the iterator + * was created. + * Whenever the iterator is iterated, the value is compared to the + * value of the master cookie. If they are different, a concurrent + * modification happened to the iterator and a resync is needed. + */ #define GST_ITERATOR_COOKIE(it) (GST_ITERATOR(it)->cookie) +/** + * GST_ITERATOR_ORIG_COOKIE: + * @it: the #GstIterator to get the master cookie of + * + * Macro to get a pointer to where the master cookie is stored. The + * master cookie protects the structure being iterated and gets updated + * whenever the datastructure changes. + */ #define GST_ITERATOR_ORIG_COOKIE(it) (GST_ITERATOR(it)->master_cookie) +/** + * GstIterator: + * @next: The function to get the next item in the iterator + * @item: The function to be called for each item retrieved + * @resync: The function to call when a resync is needed. + * @free: The function to call when the iterator is freed + * @pushed: The iterator that is currently pushed with gst_iterator_push() + * @type: The type of the object that this iterator will return + * @lock: The lock protecting the data structure and the cookie. + * @cookie: The cookie; the value of the master_cookie when this iterator was + * created. + * @master_cookie: A pointer to the master cookie. + * + * GstIterator base structure. The values of this structure are + * protected for subclasses, use the methods to use the #GstIterator. + */ struct _GstIterator { + /*< protected >*/ GstIteratorNextFunction next; GstIteratorItemFunction item; GstIteratorResyncFunction resync;