gnomemm r1411 - in gstreamermm/trunk: . docs gstreamer/src tests tools/m4



Author: jaalburqu
Date: Tue Mar 18 23:36:18 2008
New Revision: 1411
URL: http://svn.gnome.org/viewvc/gnomemm?rev=1411&view=rev

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

	* tools/m4/class_boxedtype_ncopy.m4: 
	* tools/m4/convert.m4: Added wrapper to be used with GstStructure
	which with GstCaps wants wrapper to work with original gobject and not
	to be delete when its ownership has been taken over by the GstCaps.

	* gstreamer/src/structure.hg: Modified Gst::Structure to use
	_CLASS_BOXED_TYPE_NCOPY so that it mostly doesn't copy the gobject and
	is flexible at destroying underlying gobject when wrapper is destroyed
	which makes it easier for Gst::Caps to "take ownership" of
	Gst::Structures

	* gstreamer/src/caps.ccg:
	* gstreamer/src/caps.hg: Reimplemented get_structure() to function
	properly and to return a const Gst::Structure*.  Modified
	create(Gst::Structure&) to "take ownership" of the Gst::Structure (as
	GstCaps does with underlying gobject).  Also handwrote
	append_structure() and merge_structure() to "take ownership" of the
	Gst::Structure which is appended/merged (as GstCaps does with
	underlying gobject)

	* tests/Makefile.am:
	* tests/test-caps-structures.cc: Added test to add/remove and get
	Gst::Structures in a Gst::Caps

	* docs/Makefile.am: Added copyright statement at top

Added:
   gstreamermm/trunk/tests/test-caps-structures.cc
   gstreamermm/trunk/tools/m4/class_boxedtype_ncopy.m4
Modified:
   gstreamermm/trunk/ChangeLog
   gstreamermm/trunk/docs/Makefile.am
   gstreamermm/trunk/gstreamer/src/caps.ccg
   gstreamermm/trunk/gstreamer/src/caps.hg
   gstreamermm/trunk/gstreamer/src/structure.hg
   gstreamermm/trunk/tests/Makefile.am
   gstreamermm/trunk/tools/m4/convert.m4

Modified: gstreamermm/trunk/docs/Makefile.am
==============================================================================
--- gstreamermm/trunk/docs/Makefile.am	(original)
+++ gstreamermm/trunk/docs/Makefile.am	Tue Mar 18 23:36:18 2008
@@ -1,3 +1,6 @@
+## Copyright (c) 2008
+## The gstreamermm development team.
+
 SUBDIRS=reference
 
 

Modified: gstreamermm/trunk/gstreamer/src/caps.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/caps.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/caps.ccg	Tue Mar 18 23:36:18 2008
@@ -21,6 +21,7 @@
 
 #include <gst/gstcaps.h>
 #include <gstreamermm/structure.h>
+#include <map>
 
 namespace Gst
 {
@@ -49,36 +50,72 @@
 Glib::RefPtr<Caps>
 Caps::create(Structure& structure)
 {
+  //Since caps now owns structure, do not let wrapper destroy structure (caps
+  //will do that itself)
+  structure.set_destroy(false);
+
   return Glib::wrap(gst_caps_new_full(structure.gobj()));
 }
 
+void Caps::append_structure(Structure& structure)
+{
+  //Since caps now owns structure, do not let wrapper destroy structure (caps
+  //will do that itself)
+  structure.set_destroy(false);
+
+  gst_caps_append_structure(gobj(), structure.gobj());
+}
+
+void Caps::merge_structure(Structure& structure)
+{
+  //Since caps now owns structure, do not let wrapper destroy structure (caps
+  //will do that itself)
+  structure.set_destroy(false);
+
+  gst_caps_merge_structure(gobj(), structure.gobj());
+}
+
+const Structure* Caps::get_structure(guint idx) const
+{
+  static std::map<guint,Structure> structures;
+
+  GstStructure* structure = gst_caps_get_structure(gobj(), idx);
+
+  if (structure)
+  {
+    if (structures[idx].gobj() != structure) {
+      Structure temp(structure, false /*don't copy*/, false /*don't destroy*/);
+      structures[idx].swap(temp);
+    }
+    return &structures[idx];
+  }
+
+  return NULL;
+}
+
 //TODO: Want to return RefPtr to Caps but using RefPtr in expressions such
 //TODO: as 'caps->set_simple(name1, value1)->set_simple(name2, value2)' a
 //TODO: causes Structure immutability warnings because the Caps is referenced
 //TODO: more than once in the expression
 /*
-  This method is implemented because gst_caps_set_simple is a variable argument
-  function and cannot be wrapped.  In addition, in order for
-  gst_caps_set_simple to work, this Caps must be "simple", ie, it must only
-  have one GstStructure (gst_caps_set_simple checks for this).  Here we must
-  set the field in the Structure ourselves so we must check for only one
-  Structure ourselves also (because we wont be calling gst_caps_set_simple)
+  This method is implemented in place of gst_caps_set_simple which is a
+  variable argument function and cannot be wrapped.  We don't call
+  gst_caps_set_simple() directly because we are using a Glib::ValueBase as the
+  value to be set instead of listing out each field in the value as would be
+  done with gst_caps_set_simple()
 */
 //Glib::RefPtr<Caps>
 void
 Caps::set_simple(const Glib::ustring& name, const Glib::ValueBase& value)
 {
-  //g_return_val_if_fail((gobj()->structs->len == 1), Glib::RefPtr<Caps>());
-  g_return_if_fail((gobj()->structs->len == 1));
-  gst_structure_set_value(gst_caps_get_structure(gobj(), 0), name.c_str(), value.gobj());
+  g_return_if_fail((gobj()->structs->len == 1)); // Not simple
+  g_return_if_fail (g_atomic_int_get(&(gobj())->refcount) == 1); // IS_WRITABLE(caps) fails
 
-  //return Glib::wrap(gobj(), true);
-}
+  //Use Gst::Structure so gstremermm GTypes like Gst::Value<Gst::IntRange> are
+  //converted to GStreamer types when they are stored in structure
+  const_cast<Structure*>(get_structure(0))->set_field(name, value);
 
-const Structure& Caps::get_structure(guint idx) const
-{
-  const_cast<Caps*>(this)->structure_ = Structure(gst_caps_get_structure(gobj(), idx));
-  return structure_;
+  //return Glib::wrap(gobj(), true);
 }
 
 } //namespace Gst

Modified: gstreamermm/trunk/gstreamer/src/caps.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/caps.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/caps.hg	Tue Mar 18 23:36:18 2008
@@ -82,20 +82,27 @@
   _WRAP_METHOD(Glib::RefPtr<Caps> copy_nth(guint nth), gst_caps_copy_nth)
   _WRAP_METHOD(void append(const Glib::RefPtr<Caps>& caps), gst_caps_append)
   _WRAP_METHOD(void merge(const Glib::RefPtr<Caps>& caps), gst_caps_merge)
-  _WRAP_METHOD(void append_structure(Structure& structure), gst_caps_append_structure)
-  _WRAP_METHOD(void merge_structure(Structure& structure), gst_caps_merge_structure)
 
-  /** Finds the structure in caps that has the index index, and returns it.
+  /** Appends structure to caps. The structure is not copied; caps becomes the
+   * owner of structure.
    *
-   * @param index the index of the structure
-   * @return the Structure corresponding to index
+   * @param structure the Structure to append
+   */
+  void append_structure(Structure& structure);
+
+  /** Appends structure to caps if its not already expressed by caps. The
+   * structure is not copied; caps becomes the owner of structure.
+   *
+   * @param structure the Structure to merge
    */
+  void merge_structure(Structure& structure);
 
-  /** (Please note that when Structures are assigned, the original is copied
-   * which means that the copy may be modifiable but the original never is.
-   * Also, if the original changes for any reason, the copy will not.)
+  /** Finds the structure in caps that has the index idx, and returns it.
+   *
+   * @param index the index of the structure
+   * @return the Structure corresponding to index
    */
-  const Structure& get_structure(guint idx) const;
+  const Structure* get_structure(guint idx) const;
 
   _WRAP_METHOD(void remove_structure(guint idx), gst_caps_remove_structure)
   _WRAP_METHOD(guint get_size() const, gst_caps_get_size)
@@ -133,10 +140,6 @@
   _WRAP_METHOD(void truncate(), gst_caps_truncate)
   
   _IGNORE(gst_caps_copy, gst_caps_set_simple, gst_caps_make_writable)
-
-private:
-  Structure structure_;
-  
 };
 
 } //namespace Gst

Modified: gstreamermm/trunk/gstreamer/src/structure.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/structure.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/structure.hg	Tue Mar 18 23:36:18 2008
@@ -44,7 +44,7 @@
  */
 class Structure
 {
-  _CLASS_BOXEDTYPE(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
+  _CLASS_BOXEDTYPE_NCOPY(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
 
 public:
   /** For example,

Modified: gstreamermm/trunk/tests/Makefile.am
==============================================================================
--- gstreamermm/trunk/tests/Makefile.am	(original)
+++ gstreamermm/trunk/tests/Makefile.am	Tue Mar 18 23:36:18 2008
@@ -5,7 +5,7 @@
 noinst_PROGRAMS = test-caps test-create-element test-pipeline-add-element \
                   test-link-elements test-create-bin test-miniobject-wrap \
                   test-message-wrap test-event-wrap test-query-wrap \
-		  test-structure
+		  test-structure test-caps-structures
 
 test_caps_SOURCES=test-caps.cc
 test_caps_LDFLAGS= GSTREAMERMM_LIBS@
@@ -37,6 +37,9 @@
 test_structure_SOURCES=test-structure.cc
 test_structure_LDFLAGS= GSTREAMERMM_LIBS@
 
+test_caps_structures_SOURCES=test-caps-structures.cc
+test_caps_structures_LDFLAGS= GSTREAMERMM_LIBS@
+
 #runtestbasic runtestlangs \
 #runtestsearch runtestmimetypes \
 #runtestgetbuffer

Added: gstreamermm/trunk/tests/test-caps-structures.cc
==============================================================================
--- (empty file)
+++ gstreamermm/trunk/tests/test-caps-structures.cc	Tue Mar 18 23:36:18 2008
@@ -0,0 +1,67 @@
+// -*- 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>
+
+void add_structures(const Glib::RefPtr<Gst::Caps>& caps)
+{
+  Gst::Structure struct1("Structure 1");
+  Gst::Structure struct2("Structure 2");
+  Gst::Structure struct3("Structure 3");
+
+  Glib::Value<Glib::ustring> message;
+  message.init(Glib::Value<Glib::ustring>::value_type());
+
+  message.set("Message 1");
+  struct1.set_field("message", message);
+
+  message.set("Message 2");
+  struct2.set_field("message", message);
+
+  message.set("Message 3");
+  struct3.set_field("message", message);
+
+  caps->append_structure(struct1);
+  caps->append_structure(struct2);
+  caps->append_structure(struct3);
+}
+
+int main (int argc, char* argv[])
+{
+  Gst::init(argc, argv);
+
+  Glib::RefPtr<Gst::Caps> caps = Gst::Caps::create();
+  add_structures(caps);
+
+  for (int i = 0; i < 2; i++) {
+    Glib::Value<Glib::ustring> v;
+    const Gst::Structure* s = caps->get_structure(i);
+    s->get_field("message", v);
+    std::cout << s->get_name() << ": " << v.get() << std::endl;
+  }
+
+  caps->remove_structure(1);
+
+  std::cout << "Caps structure index 1 = " << caps->get_structure(1)->get_name() << std::endl;
+
+  return 0;
+}

Added: gstreamermm/trunk/tools/m4/class_boxedtype_ncopy.m4
==============================================================================
--- (empty file)
+++ gstreamermm/trunk/tools/m4/class_boxedtype_ncopy.m4	Tue Mar 18 23:36:18 2008
@@ -0,0 +1,236 @@
+dnl Modified from class_boxed_type.m4 in glibmm (designed to work in a similar
+dnl fashion except that the gobject is not copied if it can be helped)
+
+define(`_CLASS_BOXEDTYPE_NCOPY',`dnl
+_PUSH()
+dnl
+dnl  Define the args for later macros
+define(`__CPPNAME__',`$1')
+define(`__CNAME__',`$2')
+define(`__BOXEDTYPE_FUNC_NEW',`$3')
+define(`__BOXEDTYPE_FUNC_COPY',`$4')
+define(`__BOXEDTYPE_FUNC_FREE',`$5')
+
+define(`_CUSTOM_DEFAULT_CTOR',`dnl
+_PUSH()
+dnl Define this macro to be tested for later.
+define(`__BOOL_CUSTOM_DEFAULT_CTOR__',`$1')
+_POP()
+')
+
+
+_POP()
+_SECTION(SECTION_CLASS2)
+') dnl End of _CLASS_BOXEDTYPE_NCOPY.
+
+dnl Some of the Gdk types are unions - e.g. GdkEvent.
+define(`_CUSTOM_STRUCT_PROTOTYPE',`dnl
+_PUSH()
+dnl Define this macro to be tested for later.
+define(`__BOOL_CUSTOM_STRUCT_PROTOTYPE__',`$1')
+_POP()
+')
+
+dnl
+dnl _END_CLASS_BOXEDTYPE_NCOPY()
+dnl   denotes the end of a class
+dnl
+define(`_END_CLASS_BOXEDTYPE_NCOPY',`
+_SECTION(SECTION_HEADER1)
+ifdef(`__BOOL_CUSTOM_STRUCT_PROTOTYPE__',`dnl
+',`dnl
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _`'__CNAME__ __CNAME__; }
+#endif
+')dnl
+
+_SECTION(SECTION_HEADER3)
+
+__NAMESPACE_BEGIN__
+
+/** @relates __NAMESPACE__::__CPPNAME__
+ * @param lhs The left-hand side
+ * @param rhs The right-hand side
+ */
+inline void swap(__CPPNAME__& lhs, __CPPNAME__& rhs)
+  { lhs.swap(rhs); }
+
+__NAMESPACE_END__
+
+namespace Glib
+{
+ifdef(`__BOOL_NO_WRAP_FUNCTION__',`dnl
+',`dnl else
+
+/** A Glib::wrap() method for this object.
+ * 
+ * @param object The C instance.
+ * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
+ * @param destroy False if the result should not delete the C instance when wrapper is destroyed. True if it should.
+ * @result A C++ instance that wraps this C instance.
+ *
+ * @relates __NAMESPACE__::__CPPNAME__
+ */
+__NAMESPACE__::__CPPNAME__ wrap(__CNAME__* object, bool take_copy = false, bool destroy = true);
+')dnl endif __BOOL_NO_WRAP_FUNCTION__
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <>
+class Value<__NAMESPACE__::__CPPNAME__> : public Glib::Value_Boxed<__NAMESPACE__::__CPPNAME__>
+{};
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+_SECTION(SECTION_SRC_GENERATED)
+
+ifdef(`__BOOL_NO_WRAP_FUNCTION__',`dnl
+',`dnl else
+namespace Glib
+{
+
+__NAMESPACE__::__CPPNAME__ wrap(__CNAME__* object, bool take_copy, bool destroy)
+{
+  return __NAMESPACE__::__CPPNAME__`'(object, take_copy, destroy);
+}
+
+} // namespace Glib
+')dnl endif
+
+
+__NAMESPACE_BEGIN__
+
+dnl
+dnl The implementation:
+dnl
+
+// static
+GType __CPPNAME__::get_type()
+{
+  return _GET_TYPE_FUNC(__CNAME__);
+}
+
+ifdef(`__BOOL_CUSTOM_DEFAULT_CTOR__',`dnl
+',`dnl else
+__CPPNAME__::__CPPNAME__`'()
+:
+ifelse(__BOXEDTYPE_FUNC_NEW,NONE,`dnl
+  gobject_ (0), // Allows creation of invalid wrapper, e.g. for output arguments to methods.
+  destroy(false)  // destroy tells whether to free gobject when wrapper is destroyed
+',`dnl else
+  gobject_ (__BOXEDTYPE_FUNC_NEW`'())
+')dnl
+{}
+')dnl endif __BOOL_CUSTOM_DEFAULT_CTOR__
+
+__CPPNAME__::__CPPNAME__`'(const __CPPNAME__& other)
+:
+  gobject_ (other.gobject_),  // Always use original object
+  destroy(false)  // Do not delete gobject when wrapper is destroyed (let
+                  // original wrapper do that)
+{}
+
+__CPPNAME__::__CPPNAME__`'(__CNAME__* gobject, bool make_a_copy, bool destroy)
+:
+  // For this ncopy BoxedType wrapper, make_a_copy is false by default
+  // and destroy is true.
+  gobject_ ((make_a_copy && gobject) ? __BOXEDTYPE_FUNC_COPY`'(gobject) : gobject),
+  destroy(destroy) // Should wrapper destroy gobject when deleted?
+{}
+
+// operator=() DOES make copies of gobject.
+__CPPNAME__& __CPPNAME__::operator=(const __CPPNAME__`'& other)
+{
+  __CPPNAME__ temp (gobject_, true);
+  swap(temp);
+  return *this;
+}
+
+__CPPNAME__::~__CPPNAME__`'()
+{
+dnl This could be a free or an unref, we do not need to know.
+  if(destroy && gobject_)
+    __BOXEDTYPE_FUNC_FREE`'(gobject_);
+}
+
+void __CPPNAME__::swap(__CPPNAME__& other)
+{
+  __CNAME__ *const temp = gobject_;
+  gobject_ = other.gobject_;
+  other.gobject_ = temp;
+
+  bool const destroy_temp = destroy;
+  destroy = other.destroy;
+  other.destroy = destroy_temp;
+}
+
+__CNAME__* __CPPNAME__::gobj_copy() const
+{
+  return __BOXEDTYPE_FUNC_COPY`'(gobject_);
+}
+
+//
+void __CPPNAME__::set_destroy(bool destroy)
+{
+  this->destroy = destroy;
+}
+
+_IMPORT(SECTION_CC)
+
+__NAMESPACE_END__
+
+
+dnl
+dnl
+dnl
+dnl
+_POP()
+dnl
+dnl
+dnl The actual class, e.g. Pango::FontDescription, declaration:
+dnl
+_IMPORT(SECTION_CLASS1)
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  typedef __CPPNAME__ CppObjectType;
+  typedef __CNAME__ BaseObjectType;
+
+  static GType get_type() G_GNUC_CONST;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ifdef(`__BOOL_CUSTOM_DEFAULT_CTOR__',`dnl
+',`dnl else
+  __CPPNAME__`'();
+')dnl
+
+  explicit __CPPNAME__`'(__CNAME__* gobject, bool make_a_copy = false, bool destroy = true);
+
+  __CPPNAME__`'(const __CPPNAME__& other);
+  __CPPNAME__& operator=(const __CPPNAME__& other);
+
+  ~__CPPNAME__`'();
+
+  void swap(__CPPNAME__& other);
+
+  ///Provides access to the underlying C instance.
+  __CNAME__*       gobj()       { return gobject_; }
+
+  ///Provides access to the underlying C instance.
+  const __CNAME__* gobj() const { return gobject_; }
+
+  ///Provides access to the underlying C instance. The caller is responsible for freeing it. Use when directly setting fields in structs.
+  __CNAME__* gobj_copy() const;
+
+  //Change whether wrapper should destroy gobject or not when wrapper is deleted.
+  void set_destroy(bool destroy);
+
+protected:
+  __CNAME__* gobject_;
+
+private:
+  bool destroy;
+
+private:
+_IMPORT(SECTION_CLASS2)
+')
+

Modified: gstreamermm/trunk/tools/m4/convert.m4
==============================================================================
--- gstreamermm/trunk/tools/m4/convert.m4	(original)
+++ gstreamermm/trunk/tools/m4/convert.m4	Tue Mar 18 23:36:18 2008
@@ -2,3 +2,4 @@
 include(convert_glib.m4)
 include(convert_gst.m4)
 include(class_gstminiobject.m4)
+include(class_boxedtype_ncopy.m4)



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