[farsight2/master] Add utility to be notified when an element is added to a bin or a sub-bin

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:20:41 PST 2008


---
 docs/libs/farsight-libs-docs.sgml    |    4 +
 docs/libs/farsight-libs-sections.txt |   10 ++
 gst-libs/gst/farsight/Makefile.am    |    6 +-
 gst-libs/gst/farsight/fs-utils.c     |  236 ++++++++++++++++++++++++++++++++++
 gst-libs/gst/farsight/fs-utils.h     |   59 +++++++++
 5 files changed, 313 insertions(+), 2 deletions(-)
 create mode 100644 gst-libs/gst/farsight/fs-utils.c
 create mode 100644 gst-libs/gst/farsight/fs-utils.h

diff --git a/docs/libs/farsight-libs-docs.sgml b/docs/libs/farsight-libs-docs.sgml
index 5618b73..2016b55 100644
--- a/docs/libs/farsight-libs-docs.sgml
+++ b/docs/libs/farsight-libs-docs.sgml
@@ -24,6 +24,10 @@
     <xi:include href="xml/fs-base-conference.xml"/>
   </chapter>
   <chapter>
+    <title>Farsight Utility Functions</title>
+    <xi:include href="xml/fs-utils.xml"/>
+  </chapter>
+  <chapter>
     <title>Farsight Transmitter objects</title>
     <xi:include href="xml/fs-transmitter.xml"/>
     <xi:include href="xml/fs-stream-transmitter.xml"/>
diff --git a/docs/libs/farsight-libs-sections.txt b/docs/libs/farsight-libs-sections.txt
index 4749dbc..eaacabe 100644
--- a/docs/libs/farsight-libs-sections.txt
+++ b/docs/libs/farsight-libs-sections.txt
@@ -211,3 +211,13 @@ fs_plugin_get_type
 fs_marshal_VOID__BOXED_BOXED
 fs_marshal_VOID__OBJECT_INT_STRING_STRING
 </SECTION>
+
+<SECTION>
+<FILE>fs-utils</FILE>
+<TITLE>Utils</TITLE>
+FsElementAddedCallback
+fs_utils_add_recursive_element_added_notification
+fs_utils_remove_recursive_element_added_notification
+<SUBSECTION Private>
+fs_utils_recursive_element_added
+</SECTION>
diff --git a/gst-libs/gst/farsight/Makefile.am b/gst-libs/gst/farsight/Makefile.am
index 0773b90..914f9f1 100644
--- a/gst-libs/gst/farsight/Makefile.am
+++ b/gst-libs/gst/farsight/Makefile.am
@@ -12,7 +12,8 @@ libgstfarsightinclude_HEADERS = \
 		fs-stream-transmitter.h \
 		fs-plugin.h \
 		fs-marshal.h \
-		fs-enum-types.h
+		fs-enum-types.h \
+		fs-utils.h
 
 lib_LTLIBRARIES = libgstfarsight- at GST_MAJORMINOR@.la
 
@@ -34,7 +35,8 @@ libgstfarsight_ at GST_MAJORMINOR@_la_SOURCES = \
 		fs-stream-transmitter.c \
 		fs-plugin.c \
 		fs-marshal.c \
-		fs-enum-types.c
+		fs-enum-types.c \
+		fs-utils.c
 
 EXTRA_libgstfarsight_ at GST_MAJORMINOR@_la_SOURCES = fs-marshal.list
 
diff --git a/gst-libs/gst/farsight/fs-utils.c b/gst-libs/gst/farsight/fs-utils.c
new file mode 100644
index 0000000..1d9cc18
--- /dev/null
+++ b/gst-libs/gst/farsight/fs-utils.c
@@ -0,0 +1,236 @@
+/*
+ * Farsight2 - Utility functions
+ *
+ * Copyright 2007 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ * Copyright 2007 Nokia Corp.
+ *
+ * fs-session.h - A Farsight Session gobject (base implementation)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+/**
+ * SECTION:fs-utils
+ * @short_description: Various utility functions
+ *
+ * This file contains various utility functions for farsight
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fs-utils.h"
+
+struct FsElementAddedData {
+  gint refcount;
+  FsElementAddedCallback callback;
+  gpointer user_data;
+  GstBin *head;
+};
+
+
+static gpointer _element_added_callback (GstBin *parent, GstElement *element,
+    gpointer user_data);
+
+
+static struct FsElementAddedData *
+element_added_data_new (FsElementAddedCallback callback, gpointer user_data,
+                        GstBin *head)
+{
+  struct FsElementAddedData *data =
+    g_new (struct FsElementAddedData, 1);
+
+  data->refcount = 0;
+  data->callback = callback;
+  data->user_data = user_data;
+  data->head = head;
+
+  return data;
+}
+
+static void
+element_added_data_inc (struct FsElementAddedData *data)
+{
+  g_atomic_int_inc (&data->refcount);
+}
+
+
+static void
+element_added_data_dec (struct FsElementAddedData *data)
+{
+  if (g_atomic_int_dec_and_test (&data->refcount))
+  {
+    g_free (data);
+  }
+}
+
+
+static void
+_bin_unparented_cb (GstObject *object, GstObject *parent, gpointer user_data)
+{
+  GstIterator *iter = NULL;
+  gboolean done;
+
+  /* Return if there was no handler connected */
+  if (g_signal_handlers_disconnect_by_func(object, _element_added_callback,
+          user_data) == 0)
+    return;
+
+  iter = gst_bin_iterate_elements (GST_BIN (object));
+
+  done = FALSE;
+  while (!done)
+  {
+    gpointer item;
+
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+        {
+        if (GST_IS_BIN (item))
+          _bin_unparented_cb (GST_OBJECT (item), object, user_data);
+        }
+        break;
+      case GST_ITERATOR_RESYNC:
+        // We don't rollback anything, we just ignore already processed ones
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        g_error ("Wrong parameters were given?");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+    }
+  }
+
+  gst_iterator_free (iter);
+}
+
+static gpointer
+_element_added_callback (GstBin *parent, GstElement *element,
+    gpointer user_data)
+{
+  struct FsElementAddedData *data = user_data;
+
+  if (GST_IS_BIN (element)) {
+    GstIterator *iter = NULL;
+    gboolean done;
+
+    element_added_data_inc (data);
+    g_object_weak_ref (G_OBJECT (element), (GWeakNotify) element_added_data_dec,
+        user_data);
+    g_signal_connect (element, "element-added",
+        G_CALLBACK (_element_added_callback), user_data);
+
+    if (data->head != GST_BIN_CAST (element))
+      g_signal_connect (element, "parent-unset",
+          G_CALLBACK (_bin_unparented_cb), user_data);
+
+    iter = gst_bin_iterate_elements (GST_BIN (element));
+
+    done = FALSE;
+    while (!done)
+    {
+      gpointer item = NULL;
+
+      switch (gst_iterator_next (iter, &item)) {
+       case GST_ITERATOR_OK:
+         /* We make sure the callback has not already been added */
+         if (g_signal_handler_find (item,
+                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+                 0, 0, NULL, /* id, detail, closure */
+                 _element_added_callback, user_data) == 0)
+           _element_added_callback (GST_BIN_CAST (element), item, user_data);
+         gst_object_unref (item);
+         break;
+       case GST_ITERATOR_RESYNC:
+         // We don't rollback anything, we just ignore already processed ones
+         gst_iterator_resync (iter);
+         break;
+       case GST_ITERATOR_ERROR:
+         g_error ("Wrong parameters were given?");
+         done = TRUE;
+         break;
+       case GST_ITERATOR_DONE:
+         done = TRUE;
+         break;
+     }
+    }
+
+    gst_iterator_free (iter);
+  }
+
+  data->callback (parent, element, data->user_data);
+
+  return data;
+}
+
+/**
+ * fs_utils_add_recursive_element_added_notification:
+ * @bin: A #GstBin
+ * @callback: the function to be called when a new element is added
+ * @user_data: data that will be passed to the callback
+ *
+ * The callback will be called on every element currently inside the bin,
+ * and this will be done recursively. The function will also be called on any
+ * element added in the future to the bin. The callback may be called more than
+ * once and should be thread safe (elements may be added from the streaming
+ * threads).
+ *
+ * Returns: a handle that can be used when calling
+ *  #fs_utils_remove_recursive_element_added_notification
+ */
+
+gpointer
+fs_utils_add_recursive_element_added_notification (GstBin *bin,
+    FsElementAddedCallback callback,
+    gpointer user_data)
+{
+  g_assert (callback);
+  g_assert (GST_IS_BIN (bin));
+
+  return _element_added_callback (NULL, GST_ELEMENT_CAST (bin),
+      element_added_data_new (callback, user_data, bin));
+}
+
+/**
+ * fs_utils_remove_recursive_element_added_notification:
+ * @bin: a #GstBin on which fs_utils_add_recursive_element_added_notification
+ *   has been called
+ * @handle: the handle returned by
+ *     #fs_utils_add_recursive_element_added_notification
+ *
+ * This function will remove the callback added by
+ * #fs_utils_add_recursive_element_added_notification
+ */
+void
+fs_utils_remove_recursive_element_added_notification (GstBin *bin,
+    gpointer handle)
+{
+  struct FsElementAddedData *data = handle;
+
+ if (g_signal_handler_find (bin,
+                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+                 0, 0, NULL, /* id, detail, closure */
+                 _element_added_callback, data) != 0)
+ {
+   g_assert (data->head == bin);
+   _bin_unparented_cb (GST_OBJECT (data->head), NULL, data);
+ }
+}
diff --git a/gst-libs/gst/farsight/fs-utils.h b/gst-libs/gst/farsight/fs-utils.h
new file mode 100644
index 0000000..b40c79e
--- /dev/null
+++ b/gst-libs/gst/farsight/fs-utils.h
@@ -0,0 +1,59 @@
+/*
+ * Farsight2 - Utility functions
+ *
+ * Copyright 2007 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ * Copyright 2007 Nokia Corp.
+ *
+ * fs-session.h - A Farsight Session gobject (base implementation)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef __FS_UTILS_H__
+#define __FS_UTILS_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/**
+ * FsElementAddedCallback:
+ * @bin: The #GstBin to which the element was added
+ * @element: The just-added #GstElement
+ * @user_data: The user data passed by the user
+ *
+ * The callback used by #fs_utils_add_recursive_element_added_notification
+ */
+
+typedef void (*FsElementAddedCallback) (GstBin *bin,
+    GstElement *element,
+    gpointer user_data);
+
+void fs_utils_recursive_element_added (GstBin *bin,
+    FsElementAddedCallback callback,
+    gpointer user_data);
+
+gpointer fs_utils_add_recursive_element_added_notification (GstBin *bin,
+    FsElementAddedCallback callback,
+    gpointer user_data);
+
+void fs_utils_remove_recursive_element_added_notification (GstBin *bin,
+    gpointer handle);
+
+
+G_END_DECLS
+
+#endif /* __FS_UTILS_H__ */
-- 
1.5.6.5




More information about the farsight-commits mailing list