gnomemm r1665 - in gstreamermm/trunk: . gstreamer gstreamer/src gstreamerbase gstreamerbase/src tests tools/m4



Author: jaalburqu
Date: Fri Aug  8 21:31:39 2008
New Revision: 1665
URL: http://svn.gnome.org/viewvc/gnomemm?rev=1665&view=rev

Log:
2008-08-08  Josà Alburquerque  <jaalburqu svn gnome org>

	* gstreamer/src/iterator.ccg:
	* gstreamer/src/iterator.hg: First cut at implementing Gst::Iterator.
	* gstreamer/gstreamermm.h:
	* gstreamer/src/Makefile_list_of_hg.am_fragment: Re-added
	Gst::Iterator after first cut at implementing it.
	* gstreamer/src/bin.hg:
	* tools/m4/convert_gst.m4: Wrapped iterate_elements() (makes use of
	Gst::Iterator).
	* tests/Makefile.am:
	* tests/test-iterator.cc: Added Gst::Iterator test.  Still need to
	test further and refine Iterator class implementations where possible.

	* gstreamerbase/gstreamerbasemm.h: Added audioclock.h.

	* gstreamerbase/src/audioclock.ccg:
	* gstreamer/src/element.hg: Typos.

Added:
   gstreamermm/trunk/tests/test-iterator.cc
Modified:
   gstreamermm/trunk/ChangeLog
   gstreamermm/trunk/gstreamer/gstreamermm.h
   gstreamermm/trunk/gstreamer/src/Makefile_list_of_hg.am_fragment
   gstreamermm/trunk/gstreamer/src/bin.hg
   gstreamermm/trunk/gstreamer/src/element.hg
   gstreamermm/trunk/gstreamer/src/iterator.ccg
   gstreamermm/trunk/gstreamer/src/iterator.hg
   gstreamermm/trunk/gstreamerbase/gstreamerbasemm.h
   gstreamermm/trunk/gstreamerbase/src/audioclock.ccg
   gstreamermm/trunk/tests/Makefile.am
   gstreamermm/trunk/tools/m4/convert_gst.m4

Modified: gstreamermm/trunk/gstreamer/gstreamermm.h
==============================================================================
--- gstreamermm/trunk/gstreamer/gstreamermm.h	(original)
+++ gstreamermm/trunk/gstreamer/gstreamermm.h	Fri Aug  8 21:31:39 2008
@@ -19,7 +19,7 @@
 #include <gstreamermm/index.h>
 #include <gstreamermm/indexfactory.h>
 #include <gstreamermm/interface.h>
-//TODO: #include <gstreamermm/iterator.h> (when wrapping of GstIterator is done)
+#include <gstreamermm/iterator.h>
 #include <gstreamermm/message.h>
 #include <gstreamermm/object.h>
 #include <gstreamermm/pad.h>

Modified: gstreamermm/trunk/gstreamer/src/Makefile_list_of_hg.am_fragment
==============================================================================
--- gstreamermm/trunk/gstreamer/src/Makefile_list_of_hg.am_fragment	(original)
+++ gstreamermm/trunk/gstreamer/src/Makefile_list_of_hg.am_fragment	Fri Aug  8 21:31:39 2008
@@ -6,7 +6,7 @@
 files_win32_hg =
 files_general_hg = bin.hg buffer.hg bus.hg caps.hg childproxy.hg clock.hg \
 	element.hg elementfactory.hg enums.hg error.hg event.hg filter.hg \
-	format.hg index.hg indexfactory.hg interface.hg \
+	format.hg index.hg indexfactory.hg interface.hg iterator.hg \
 	message.hg pad.hg padtemplate.hg parse.hg pipeline.hg \
 	plugin.hg pluginfeature.hg query.hg registry.hg segment.hg \
 	structure.hg systemclock.hg tagsetter.hg task.hg urihandler.hg \

Modified: gstreamermm/trunk/gstreamer/src/bin.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/bin.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/bin.hg	Fri Aug  8 21:31:39 2008
@@ -22,6 +22,7 @@
 #include <gstreamermm/element.h>
 #include <gstreamermm/childproxy.h>
 #include <gstreamermm/pad.h>
+#include <gstreamermm/iterator.h>
 #include <stdexcept> //Because add() throws std::runtime_error.
 
 _DEFS(gstreamermm,gst)
@@ -186,9 +187,9 @@
 
   _WRAP_METHOD(Glib::RefPtr<Pad> find_unconnected_pad(PadDirection dir), gst_bin_find_unconnected_pad)
   _WRAP_METHOD(Glib::RefPtr<const Pad> find_unconnected_pad(PadDirection dir) const, gst_bin_find_unconnected_pad)
+  _WRAP_METHOD(Iterator<Element> iterate_elements(), gst_bin_iterate_elements)
 
 /* TODO:
-GstIterator*    gst_bin_iterate_elements	 (GstBin *bin);
 GstIterator*    gst_bin_iterate_sorted		 (GstBin *bin);
 GstIterator*    gst_bin_iterate_recurse		 (GstBin *bin);
 

Modified: gstreamermm/trunk/gstreamer/src/element.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/element.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/element.hg	Fri Aug  8 21:31:39 2008
@@ -336,28 +336,29 @@
  * underlying gobject implements.
  * Gst::ElementInterfaced is a templated class which, in conjunction with
  * Gst::Interface::cast(), is used to cast a Gst::Element obtained by
- * Gst::ElementFactory::create() into underlying GStreamer interfaces that the
- * element may implement.  A 'filesrc' element, for example, implements the
- * Gst::URIHandler interface (which is not reflected in a Gst::Element obtained
- * from a Gst::ElementFactory).  To use the Gst::URIHandler methods with a
- * 'filesrc' element obtained from a Gst::ElementFactory, one would do the
- * following:
+ * Gst::ElementFactory::create_element() into underlying GStreamer interfaces
+ * that the element may implement.  A 'filesrc' element, for example,
+ * implements the Gst::URIHandler interface (which is not reflected in a
+ * Gst::Element obtained from a Gst::ElementFactory).  To use the
+ * Gst::URIHandler methods with a 'filesrc' element obtained from a
+ * Gst::ElementFactory, one would do the following:
  * @code
  * ...
- * Glib::RefPtr<Gst::Element> element = Gst::ElementFactory::create("filesrc",
- * "source");
+ * Glib::RefPtr<Gst::Element> element =
+ * Gst::ElementFactory::create_element("filesrc", "source");
  *
  * Glib::RefPtr< Gst::ElementInterfaced<Gst::URIHandler> > handler =
  *   Gst::Interface::cast<Gst::URIHandler>(element);
  *
- * if(handler)
+ * if (handler)
  * {
  *   std::cout << "element '" << element->get_name() <<
  *     "' implements URIHandler interface." << std::endl;
  *
+ *   // Use uri handler interface methods:
+ *
  *   handler->set_uri("file:///tmp/media.file");
  *
- *   // Use uri handler interface method
  *   std::cout << handler->get_name() << " uri = '" << handler->get_uri() <<
  *     "'." << std::endl;
  * }

Modified: gstreamermm/trunk/gstreamer/src/iterator.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/iterator.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/iterator.ccg	Fri Aug  8 21:31:39 2008
@@ -24,10 +24,13 @@
 namespace Gst
 {
 
-GstIterator*
-Iterator::cobj()
+ConcurrentUpdateException::ConcurrentUpdateException()
+: std::runtime_error(what())
+{}
+
+const char* ConcurrentUpdateException::what() const throw()
 {
-  return cobj_;
+  return "Concurrent update of iterator elements.  Please resync iterator.";
 }
 
 } //namespace Gst

Modified: gstreamermm/trunk/gstreamer/src/iterator.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/iterator.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/iterator.hg	Fri Aug  8 21:31:39 2008
@@ -20,6 +20,7 @@
  */
 
 #include <gst/gstiterator.h>
+#include <stdexcept>
 
 _DEFS(gstreamermm,gst)
 
@@ -29,19 +30,289 @@
 _WRAP_ENUM(IteratorItem, GstIteratorItem)
 _WRAP_ENUM(IteratorResult, GstIteratorResult)
 
-class Iterator
+/** Exception thrown by Gst::IteratorBase<> increment operators when the
+ * elements are updated after element processing is underway by the iterator.
+ */
+class ConcurrentUpdateException : std::runtime_error
 {
 public:
+  ConcurrentUpdateException();
+  virtual const char* what() const throw();
+};
 
-  _CLASS_GENERIC(Iterator, GstIterator)
-
-  GstIterator* cobj();
-  Iterator(GstIterator*);
+/**  Gst::IteratorBase â Base class for classes that retrieve multiple elements
+ * in a thread safe way.
+ *
+ * Classes derived from Gst::IteratorBase are used to retrieve multiple objects
+ * from another object in a thread safe way.
+ *
+ * Various GStreamer objects provide access to their internal structures using
+ * an iterator.
+ */
+template <class CppType>
+class IteratorBase
+{
+public:
+  /** Frees the underlying C instance if a destroy value of true was used to
+   * wrap it.
+   */
+  virtual ~IteratorBase();
+
+  /** Move to the next iterator item.
+   *
+   * @return The result of the iteration. Please note that a return of
+   * Gst::ITERATOR_DONE means that the iterator is on the last item.  MT safe. 
+   */
+  IteratorResult next();
+
+  /** Resync the iterator. This function is mostly called after next() returns
+   * Gst::ITERATOR_RESYNC.  In essence, the iterator is reset to the first item
+   * because a concurrent update of the iterator's list of element occurred
+   * while element processing was underway which means a call to this method is
+   * necessary.
+   */
+  void resync();
+
+  /** Tells if iterator is at start of list (not on first item, but just
+   * before it).
+   *
+   * @return true if iterator is at start of list, false otherwise.
+   */
+  bool is_start() const;
+
+  /** Tells if iterator is on the last element.
+   *
+   * @return true if iterator is at end of list, false otherwise.
+   */
+  bool is_last() const;
+
+  /** Tells whether the iterator is valid and can be dereferenced.
+   */
+  operator bool() const;
+
+  ///Provides access to the underlying C GObject.
+  GstIterator*          cobj()          { return cobject_; };
+
+  ///Provides access to the underlying C GObject.
+  const GstIterator*    cobj() const    { return cobject_; };
+
+protected:
+  /// Default constructor.
+  IteratorBase();
+
+  /** Copy constructor.  Please note that copying and assigning merely shares
+   * the underlying C object.  Operations on the copy are also performed in the
+   * underlying C object of the original and if the original is destroyed, the
+   * copy is invalid.
+   */
+  IteratorBase(const IteratorBase<CppType>&);
+
+  /** Construct an IteratorBase from an underlying C object.
+   * @param castitem The underlying C object.
+   * @param destroy Whether to destroy underlying C object along with the
+   * wrapper.
+   */
+  IteratorBase(GstIterator* castitem, bool destroy=true);
+
+  /** Assignment operator.  It replaces the contents of this iterator with the
+   * contents of the new one freeing the underlying C object if a destroy value
+   * of true was used when wrapping it.  Please note that copying and assigning
+   * merely shares the underlying C object.  Operations on the copy are also
+   * performed in the underlying C object of the original and if the original
+   * is destroyed, the copy is invalid.
+   */
+  IteratorBase<CppType>& operator=(const IteratorBase<CppType>& other);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  gpointer current;         // The current element the iterator is referencing.
+  IteratorResult current_result; // The current result of a next() call.
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
 private:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  GstIterator* cobject_;    // The underlying  C object.
+  bool destroy;             // Whether to destroy C object with the wrapper.
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
-  GstIterator* cobj_;
+private:
+  void swap(IteratorBase<CppType>& other);
+};
 
+/**  Gst::Iterator â Class that retrieve multiple elements in a thread safe way.
+ * Gst::Iterator iterates specifically through elements that are reference
+ * counted and therefore dereferencing the elements of the iterator yields a
+ * Glib::RefPtr<> to the C++ element type.
+ */
+template <class CppType>
+class Iterator : public IteratorBase<CppType>
+{
+public:
+  /** Creates a Gst::Iterator wrapper for a GstIterator object.  The underlying
+   * @a castitem will be freed with the Gst::Iterator destruction.
+   *
+   * @param castitem The C instance to wrap.
+   * @param destroy Whether to destroy the underlying C object with the
+   * wrapper.
+   */
+  Iterator(GstIterator* castitem, bool destroy=true);
+
+  /** Dereference this iterator and obtain the underlying Glib::RefPtr<>.
+   */
+  Glib::RefPtr<CppType> operator*() const;
+
+  /** Prefix auto-increment operator.  It advances to the next item in the
+   * iterator.  It is faster than the postfix operator.
+   * @throw Gst::ConcurrentUpdateException.
+   * @throw std::runtime_error (when Gst::ITERATOR_ERROR is encountered).
+   */
+  Iterator<CppType>& operator++();
+
+  /** Postfix auto-increment operator.  It advances to the next item in the
+   * iterator.
+   * @throw Gst::ConcurrentUpdateException.
+   * @throw std::runtime_error (when Gst::ITERATOR_ERROR is encountered).
+   */
+  Iterator<CppType> operator++(int);
 };
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/***************** Gst::IteratorBase<CppType> ************************/
+
+template<class CppType>
+IteratorResult IteratorBase<CppType>::next()
+{
+  current_result = (Gst::IteratorResult) gst_iterator_next(cobj(), &current);
+  return current_result;
+}
+
+template<class CppType>
+void IteratorBase<CppType>::resync()
+{
+  gst_iterator_resync(cobj());
+  current = 0;
+  current_result = Gst::ITERATOR_OK;
+}
+
+template<class CppType>
+bool IteratorBase<CppType>::is_start() const
+{
+  return (current == 0 && current_result == Gst::ITERATOR_OK);
+}
+
+template<class CppType>
+bool IteratorBase<CppType>::is_last() const
+{
+  return (current != 0 && current_result == Gst::ITERATOR_DONE);
+}
+
+template<class CppType>
+IteratorBase<CppType>::operator bool() const
+{
+  return (current != 0);
+}
+template<class CppType>
+IteratorBase<CppType>::IteratorBase()
+: cobject_(0),
+  destroy(true),
+  current(0),
+  current_result(Gst::ITERATOR_OK)
+{}
+
+template<class CppType>
+IteratorBase<CppType>::IteratorBase(const IteratorBase<CppType>& other)
+  : cobject_(const_cast<GstIterator*>(other.cobj())),
+    destroy((other.cobj()) ? false : true),
+    current(other.current),
+    current_result(other.current_result)
+{}
+
+template<class CppType>
+IteratorBase<CppType>::IteratorBase(GstIterator* castitem, bool destroy)
+: cobject_(castitem),
+  destroy(destroy),
+  current(0),
+  current_result(Gst::ITERATOR_OK)
+{}
+
+template<class CppType>
+IteratorBase<CppType>& IteratorBase<CppType>::operator=(const IteratorBase<CppType>& other)
+{
+  IteratorBase temp(other);
+  swap(temp);
+  return *this;
+}
+
+template<class CppType>
+void IteratorBase<CppType>::swap(IteratorBase<CppType>& other)
+{
+  GstIterator *const temp_obj = cobject_;
+  cobject_ = other.cobject_;
+  other.cobject_ = temp_obj;
+
+  const bool temp_destroy = destroy;
+  destroy = other.destroy;
+  other.destroy = temp_destroy;
+
+  gpointer const temp_current = current;
+  current = other.current;
+  other.current = temp_current;
+
+  const IteratorResult temp_result = current_result;
+  current_result = other.current_result;
+  other.current_result = temp_result;
+}
+
+//virtual
+template<class CppType>
+IteratorBase<CppType>::~IteratorBase()
+{
+  if (destroy && cobject_)
+  {
+    gst_iterator_free(cobject_);
+    cobject_ = 0;
+  }
+}
+
+/******************* Gst::Iterator<CppType> **************************/
+
+template <class CppType>
+Iterator<CppType>::Iterator(GstIterator* castitem, bool destroy)
+  : IteratorBase<CppType>(castitem, destroy)
+{}
+
+template <class CppType>
+Glib::RefPtr<CppType> Iterator<CppType>::operator*() const
+{
+  typedef typename CppType::BaseObjectType CType;
+
+  if (this->current)
+    return Glib::wrap((CType*)(this->current));
+  else
+    return Glib::RefPtr<CppType>(0);
+}
+
+template<class CppType>
+Iterator<CppType>& Iterator<CppType>::operator++()
+{
+  const IteratorResult result = this->next();
+
+  if (result == Gst::ITERATOR_RESYNC)
+    throw ConcurrentUpdateException();
+  else if (result == Gst::ITERATOR_ERROR)
+    throw std::runtime_error("Iterator increment error.");
+
+  return *this;
+}
+
+template<class CppType>
+Iterator<CppType> Iterator<CppType>::operator++(int)
+{
+  Iterator<CppType> original = *this;
+  ++(*this);
+  return original;
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
 } //namespace Gst

Modified: gstreamermm/trunk/gstreamerbase/gstreamerbasemm.h
==============================================================================
--- gstreamermm/trunk/gstreamerbase/gstreamerbasemm.h	(original)
+++ gstreamermm/trunk/gstreamerbase/gstreamerbasemm.h	Fri Aug  8 21:31:39 2008
@@ -5,6 +5,7 @@
 
 #include <gstreamerbasemm/init.h>
 #include <gstreamerbasemm/wrap_init.h>
+#include <gstreamerbasemm/audioclock.h>
 #include <gstreamerbasemm/colorbalance.h>
 #include <gstreamerbasemm/colorbalancechannel.h>
 #include <gstreamerbasemm/xoverlay.h>

Modified: gstreamermm/trunk/gstreamerbase/src/audioclock.ccg
==============================================================================
--- gstreamermm/trunk/gstreamerbase/src/audioclock.ccg	(original)
+++ gstreamermm/trunk/gstreamerbase/src/audioclock.ccg	Fri Aug  8 21:31:39 2008
@@ -53,8 +53,7 @@
 
   //The following lines are taken verbatim from gst_audio_clock_new() after the
   //call to g_object_new() because it seems that bug #545782 will not be
-  //accepted.
-
+  //accepted:
   gobj()->func = &AudioClock_GetTime_gstreamermm_callback;
   gobj()->user_data = &slot;
 }

Modified: gstreamermm/trunk/tests/Makefile.am
==============================================================================
--- gstreamermm/trunk/tests/Makefile.am	(original)
+++ gstreamermm/trunk/tests/Makefile.am	Fri Aug  8 21:31:39 2008
@@ -10,7 +10,7 @@
 		  test-structure test-caps-structures test-interface \
 		  test-create-bus test-taglist test-tagsetter \
 		  test-init-check test-init test-init-check-noargs \
-		  test-init-noargs
+		  test-init-noargs test-iterator
 
 #TODO: Add test-pad to tests when bug #539108 is fixed.
 
@@ -73,3 +73,6 @@
 
 test_init_noargs_SOURCES=test-init-noargs.cc
 test_init_noargs_LDFLAGS= GSTREAMERMM_LIBS@
+
+test_iterator_SOURCES=test-iterator.cc
+test_iterator_LDFLAGS= GSTREAMERMM_LIBS@

Added: gstreamermm/trunk/tests/test-iterator.cc
==============================================================================
--- (empty file)
+++ gstreamermm/trunk/tests/test-iterator.cc	Fri Aug  8 21:31:39 2008
@@ -0,0 +1,71 @@
+// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+/* gstreamermm - a C++ wrapper for gstreamer
+ *
+ * Copyright 2008 The gstreamermm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gstreamermm.h>
+#include <iostream>
+
+int main (int argc, char* argv[])
+{
+  Gst::init(argc, argv);
+
+  Glib::RefPtr<Gst::Pipeline> pipeline;
+  Glib::RefPtr<Gst::Bin> bin;
+  Glib::RefPtr<Gst::Element> source, sink;
+
+  pipeline = Gst::Pipeline::create("my-pipeline");
+  bin = Gst::Bin::create("my-bin");
+
+  source = Gst::ElementFactory::create_element("fakesrc", "source");
+  sink = Gst::ElementFactory::create_element("fakesink", "sink");
+
+  bin->add(source)->add(sink);
+
+  pipeline->add(bin);
+  source->link(sink);
+
+  std::cout << "The following elements have been added to bin '" <<
+    bin->get_name() << "'." << std::endl;
+
+  int iterations = 0;
+  Gst::Iterator<Gst::Element> elements = bin->iterate_elements();
+
+  try
+  {
+    for ( ; !elements.is_last(); ++elements)
+    {
+      if (elements)
+        std::cout << (*elements)->get_name() << std::endl;
+
+      iterations++;
+    }
+    ++elements;
+  }
+  catch (std::runtime_error& e)
+  {
+    std::cout << "Runtime error while iterating through \"" <<
+      bin->get_name() << "'s\" elements." << std::endl;
+  }
+
+  std::cout << "The loop iterated " << iterations << " to print bin '" <<
+  bin->get_name() << "' elements." << std::endl;
+
+  return 0;
+}

Modified: gstreamermm/trunk/tools/m4/convert_gst.m4
==============================================================================
--- gstreamermm/trunk/tools/m4/convert_gst.m4	(original)
+++ gstreamermm/trunk/tools/m4/convert_gst.m4	Fri Aug  8 21:31:39 2008
@@ -95,6 +95,9 @@
 
 #IndexFactory
 _CONVERSION(`GstIndexFactory*',`Glib::RefPtr<IndexFactory>',`Glib::wrap($3)')
+#
+#Iterator
+_CONVERSION(`GstIterator*',`Iterator<Element>',`Iterator<Element>::Iterator($3)')
 
 #Message
 _CONVERSION(`GstMessage*',`Glib::RefPtr<Message>',`Gst::Message::wrap($3)')



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]