Re: Completed what I can in gstreamermm



On Wed, 2008-05-07 at 14:09 -0400, José Alburquerque wrote:
> >>> I wanted to let everyone know so that others are aware that there is 
> >>> still more to be done and the project can continue.  I don't think I'll 
> >>> be needed because all wrapping should be really clear, but if there 
> >>> should be any questions please don't hesitate to e-mail me.  Thank you 
> >>> all for the opportunity to exercise my programming muscles.  Take care.
> >>>     
> >>>       
> >> While preparing the NEWS file for gstreamermm-0.9.6, I was amazed at how
> >> much work you've done, some of it really difficult stuff.
> >>
> >> The media_player_gtkmm example shows how much you have achieved.
> >> Actually playing music and video is the main point of gstreamer.
>
> I didn't mention:  I plan to use some of the media_player_gtkmm code in 
> a project I'm developing.  Now that I was able to tackle some 
> challenges, it will come in handy when I work on the other project. :-)

I done some cleaning up of the API. It's mostly just small changes which
won't require much changes in your application code. For instance, it's
now ElementFactory::create_element() instead of
ElementFactory::create().

However, I am attaching the patch for a change I made to Structure, to
remove the awkward taking-ownership stuff. This is theoretically now
doing more copying than really necessary (it's a pity that it's not
reference-counted), but it makes the API much nicer. I wonder if this
causes problems for you.

I might need to do something similar for TagList.
 
-- 
Murray Cumming
murrayc murrayc com
www.murrayc.com
www.openismus.com
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1500)
+++ ChangeLog	(working copy)
@@ -1,6 +1,53 @@
 2008-05-17  Murray Cumming  <murrayc murrayc com>
 
+	* gstreamer/src/structure.ccg:
+	* gstreamer/src/structure.hg: Use _CLASS_BOXEDTYPE() instead of the 
+	custom _CLASS_BOXEDTYPE_NCOPY() macro, so we can just use this by 
+	copying it instead of having strange ownership rules.
+	Add operator bool() to check for invalid instances.
+
+	* gstreamer/src/caps.ccg:
+	* gstreamer/src/caps.hg: create(), append_structure(), 
+	merge_structure(): Take a const Structure& instead of taking ownership.
+	get_structure(): Return by value.
+	Remove set_simple_valist() because it does not seem useful.
+
+	* gstreamer/src/event.ccg:
+	* gstreamer/src/event.hg: get_structure():
 	* gstreamer/src/message.ccg:
+	* gstreamer/src/message.hg: get_structure():
+	* gstreamer/src/query.ccg:
+	* gstreamer/src/query.hg: get_structure(): Return by copy.
+
+	* examples/element_link/element_link.cc:
+	* examples/media_player_gtkmm/player_window.cc:
+	* examples/ogg_player/main.cc:
+	* examples/ogg_player_gtkmm/main.cc:
+	* examples/ogg_player_gtkmm/player_window.cc:
+	* tests/test-caps-structures.cc (main):
+	* tests/test-event-wrap.cc (main):
+	* tests/test-message-wrap.cc (main):
+	* tests/test-query-wrap.cc (main): Adapted to the changed API.
+
+2008-05-17  Murray Cumming  <murrayc murrayc com>
+
+	* gstreamer/src/bin.ccg:
+	* gstreamer/src/bin.hg: Make add() throw an exception, needed for 
+	chaining. The examples already try/catch this, assuming that it did 
+	already throw.
+	* gstreamer/src/element.ccg:
+	* gstreamer/src/element.hg: Document that link() throws an exception.
+	Include <stdexcept> so applications can catch runtime_error.
+
+	* examples/element_link/element_link.cc?
+	* examples/media_player_gtkmm/player_window.c:
+	* examples/ogg_player/main.cc:
+	* examples/ogg_player_gtkmm/player_window.cc: try/catch when using 
+	link(), because it throws an exception.
+
+2008-05-17  Murray Cumming  <murrayc murrayc com>
+
+	* gstreamer/src/message.ccg:
 	* gstreamer/src/message.hg: Implement MessageInfo::parse() and add a 
 	method overload without the debug parameter. 
 
Index: gstreamer/src/event.ccg
===================================================================
--- gstreamer/src/event.ccg	(revision 1494)
+++ gstreamer/src/event.ccg	(working copy)
@@ -37,14 +37,12 @@
   return Glib::QueryQuark(gst_event_type_to_quark(GstEventType(t)));
 }
 
-const Structure* Event::get_structure()
+Structure Event::get_structure() const
 {
   static Structure structure;
 
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_event_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_event_get_structure(const_cast<GstEvent*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 bool Event::is_downstream() const
Index: gstreamer/src/event.hg
===================================================================
--- gstreamer/src/event.hg	(revision 1494)
+++ gstreamer/src/event.hg	(working copy)
@@ -119,9 +119,9 @@
   static Glib::RefPtr<Event> wrap(GstEvent* event, bool take_copy=false);
 
   /** Get the structure of an event.
-   * @return The Gst::Structure of the event (unmodifiable)
+   * @return The Gst::Structure of the event.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
   /** Check if an event can travel downstream.
    */
Index: gstreamer/src/caps.hg
===================================================================
--- gstreamer/src/caps.hg	(revision 1494)
+++ gstreamer/src/caps.hg	(working copy)
@@ -29,9 +29,8 @@
 
 struct Structure;
 
-/** Gst::Caps — A structure describing sets of media formats.
- * Gst::Caps (capabilities) are lighweight refcounted objects describing media
- * types. They are composed of an array of Gst::Structure.
+/** Gst::Caps (capabilities) are lightweight objects describing media
+ * formats. They are composed of an array of Gst::Structure.
  *
  * Gst::Caps are exposed on Gst::PadTemplate to describe all possible types a
  * given pad can handle. They are also stored in the Gst::Registry along with a
@@ -70,13 +69,13 @@
    */
   static Glib::RefPtr<Caps> create_simple(const Glib::ustring& media_type);
 
-  /** Creates a new Gst::Caps and adds the first Gst::Structure given. The
-   * structure is not copied; the returned Gst::Caps owns the structure.
+  /** Creates a new Gst::Caps and adds the given Gst::Structure.
+   * Use append_structure() to add additional structures.
    *
    * @param first_struct the first structure to add
    * @return Returns the new Gst::Caps
    */
-  static Glib::RefPtr<Caps> create(Structure& first_struct);
+  static Glib::RefPtr<Caps> create(const Structure& first_struct);
 
   _WRAP_METHOD(static Glib::RefPtr<Caps> create_from_string(const Glib::ustring& string), gst_caps_from_string)
 
@@ -92,25 +91,27 @@
    *
    * @param structure the Gst::Structure to append
    */
-  void append_structure(Structure& structure);
+  void append_structure(const Structure& structure);
 
-  /** Appendsa  structure to caps if its not already expressed by caps. The
+  /** Appends a structure to caps if its not already expressed by caps. The
    * structure is not copied. This Caps becomes the owner of @a structure.
    *
    * @param structure the Gst::Structure to merge
    */
-  void merge_structure(Structure& structure);
+  void merge_structure(const Structure& structure);
 
   /** Finds the structure in caps that has the index @a idx, and returns it.
    *
    * @param index the index of the structure
    * @return the Gst::Structure corresponding to index
    */
-  const Structure* get_structure(guint idx) const;
+  Structure get_structure(guint idx) const;
 
   _WRAP_METHOD(void remove_structure(guint idx), gst_caps_remove_structure)
   _WRAP_METHOD(guint size() const, gst_caps_get_size)
 
+  //TODO: Avoid forcing applications to use Glib::Value<>. See what TreeModel does.
+
   /** Sets fields in a simple Gst::Caps. A simple Gst::Caps is one that only
    * has one structure.
    *
@@ -120,7 +121,8 @@
   void set_simple(const Glib::ustring& name, const Glib::ValueBase& value);
   _IGNORE(gst_caps_set_simple)
 
-  _WRAP_METHOD(void set_simple_valist(char* field, const va_list& varargs), gst_caps_set_simple_valist)
+  //This does not seem useful: _WRAP_METHOD(void set_simple_valist(char* field, const va_list& varargs), gst_caps_set_simple_valist)
+  _IGNORE(gst_caps_set_simple_valist)
 
   _WRAP_METHOD(bool is_any() const, gst_caps_is_any)
   _WRAP_METHOD(bool empty() const, gst_caps_is_empty)
Index: gstreamer/src/message.ccg
===================================================================
--- gstreamer/src/message.ccg	(revision 1499)
+++ gstreamer/src/message.ccg	(working copy)
@@ -37,15 +37,12 @@
   return Glib::QueryQuark(gst_message_type_to_quark(GstMessageType(t)));
 }
 
-const Structure*
-Message::get_structure()
+Structure Message::get_structure() const
 {
   static Structure structure;
 
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_message_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_message_get_structure(const_cast<GstMessage*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 MessageApplication::MessageApplication(GstMessage* castitem)
Index: gstreamer/src/caps.ccg
===================================================================
--- gstreamer/src/caps.ccg	(revision 1494)
+++ gstreamer/src/caps.ccg	(working copy)
@@ -26,8 +26,7 @@
 namespace Gst
 {
 
-Glib::RefPtr<Caps>
-Caps::create_any()
+Glib::RefPtr<Caps> Caps::create_any()
 {
   return Glib::wrap(gst_caps_new_any());
 }
@@ -38,8 +37,7 @@
   creates a GstStructure for the GstCaps and will not be called, we must create
   our own GstStructure here and append it to the GstCaps.
 */
-Glib::RefPtr<Caps>
-Caps::create_simple(const Glib::ustring& media_type)
+Glib::RefPtr<Caps> Caps::create_simple(const Glib::ustring& media_type)
 {
   Glib::RefPtr<Caps> result = Glib::wrap(gst_caps_new_empty());
   GstStructure* gst_struct = gst_structure_empty_new(media_type.c_str());
@@ -47,55 +45,39 @@
   return result;
 }
 
-Glib::RefPtr<Caps>
-Caps::create(Structure& structure)
+Glib::RefPtr<Caps> Caps::create(const 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()));
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  return Glib::wrap(gst_caps_new_full(copy));
 }
 
-void Caps::append_structure(Structure& structure)
+void Caps::append_structure(const 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());
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  gst_caps_append_structure(gobj(), copy);
 }
 
-void Caps::merge_structure(Structure& structure)
+void Caps::merge_structure(const 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());
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  gst_caps_merge_structure(gobj(), copy);
 }
 
-const Structure* Caps::get_structure(guint idx) 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;
+  if(structure)
+    return Structure(structure, true /* take_copy */);
+  else
+    return Structure(); //Use operator bool() to detect this.
 }
 
 //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: causes gstreamer Structure immutability warnings because the Caps is referenced
 //TODO: more than once in the expression
 /*
   This method is implemented in place of gst_caps_set_simple which is a
@@ -113,8 +95,13 @@
 
   //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);
 
+  //The result of gst_caps_get_structure() should not be modified, according to its documentation,
+  //but we are reimplementing gst_caps_set_simple() which does that:
+  GstStructure* structure = gst_caps_get_structure(gobj(), 0);
+  if(structure)
+    Structure::_set_gstructure_field(structure, name, value);
+
   //return Glib::wrap(gobj(), true);
 }
 
Index: gstreamer/src/structure.ccg
===================================================================
--- gstreamer/src/structure.ccg	(revision 1494)
+++ gstreamer/src/structure.ccg	(working copy)
@@ -58,6 +58,11 @@
   gobject_ = gst_structure_empty_new(name.c_str());
 }
 
+Structure::operator bool() const
+{
+  return gobject_ != 0;
+}
+
 void
 Structure::get_field(const Glib::ustring& name, Glib::ValueBase& value) const
 {
@@ -67,14 +72,21 @@
 Structure&
 Structure::set_field(const Glib::ustring& fieldname, const Glib::ValueBase& value)
 {
-  GType type = G_VALUE_TYPE(value.gobj());
+  _set_gstructure_field(gobj(), fieldname, value);
 
+  return *this;
+}
+
+void Structure::_set_gstructure_field(GstStructure* cstructure, const Glib::ustring& fieldname, const Glib::ValueBase& value)
+{
+  const GType type = G_VALUE_TYPE(value.gobj());
+
   if (type == Glib::Value<Fourcc>::value_type())
   {
      const Glib::Value<Fourcc>* fourcc =
         static_cast< const Glib::Value<Fourcc>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FOURCC,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FOURCC,
         fourcc->get().get_fourcc(), NULL);
   }
   else if (type == Glib::Value<IntRange>::value_type())
@@ -82,7 +94,7 @@
      const Glib::Value<IntRange>* range =
         static_cast< const Glib::Value<IntRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_INT_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_INT_RANGE,
         range->get().min, range->get().max, NULL);
   }
   else if (type == Glib::Value<DoubleRange>::value_type())
@@ -90,7 +102,7 @@
      const Glib::Value<DoubleRange>* range =
         static_cast< const Glib::Value<DoubleRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_DOUBLE_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_DOUBLE_RANGE,
         range->get().min, range->get().max, NULL);
   }
   else if (type == Glib::Value<Fraction>::value_type())
@@ -98,7 +110,7 @@
      const Glib::Value<Fraction>* fract =
         static_cast< const Glib::Value<Fraction>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FRACTION,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FRACTION,
         fract->get().num, fract->get().denom, NULL);
   }
   else if (type == Glib::Value<FractionRange>::value_type())
@@ -106,7 +118,7 @@
      const Glib::Value<FractionRange>* range =
         static_cast< const Glib::Value<FractionRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FRACTION_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FRACTION_RANGE,
          range->get().min.num, range->get().min.denom, range->get().max.num,
              range->get().max.denom, NULL);
   }
@@ -115,7 +127,7 @@
      const Glib::Value<Glib::Date>* date =
         static_cast< const Glib::Value<Glib::Date>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_DATE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_DATE,
          date->get().gobj(), NULL);
   }
   else if (type == Glib::Value<Structure>::value_type())
@@ -123,7 +135,7 @@
      const Glib::Value<Structure>* obj =
         static_cast< const Glib::Value<Structure>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_STRUCTURE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_STRUCTURE,
         obj->get().gobj(), NULL);
   }
   else if (type == Glib::Value<MiniObject>::value_type())
@@ -131,13 +143,14 @@
      const Glib::Value<MiniObject>* obj =
         static_cast< const Glib::Value<MiniObject>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_MINI_OBJECT,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_MINI_OBJECT,
         obj->get().gobj(), NULL);
   }
-  else 
-    gst_structure_set_value(gobj(), fieldname.c_str(), value.gobj());
-
-  return *this;
+  else
+  {
+    //TODO: Why not just use this instead of all the if/else stuff above? murrayc
+    gst_structure_set_value(cstructure, fieldname.c_str(), value.gobj());
+  }
 }
 
 Structure&
Index: gstreamer/src/query.ccg
===================================================================
--- gstreamer/src/query.ccg	(revision 1494)
+++ gstreamer/src/query.ccg	(working copy)
@@ -35,14 +35,10 @@
   return Glib::QueryQuark(gst_query_type_to_quark(GstQueryType(t)));
 }
 
-const Structure* Query::get_structure()
+Structure Query::get_structure() const
 {
-  static Structure structure;
-
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_query_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_query_get_structure(const_cast<GstQuery*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 bool get_details(QueryType type, QueryTypeDefinition &def)
Index: gstreamer/src/query.hg
===================================================================
--- gstreamer/src/query.hg	(revision 1494)
+++ gstreamer/src/query.hg	(working copy)
@@ -49,10 +49,11 @@
   _CLASS_GSTMINIOBJECT(Query, GstQuery, GST_QUERY, Gst::MiniObject, GstMiniObject)
 
 public:
+
   /** Get the structure of a query.
-   * @return The Structure of the query (unmodifiable)
+   * @return The Structure of the query.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
 public:
   _MEMBER_GET(query_type, type, QueryType, GstQueryType)
Index: gstreamer/src/message.hg
===================================================================
--- gstreamer/src/message.hg	(revision 1500)
+++ gstreamer/src/message.hg	(working copy)
@@ -59,10 +59,11 @@
  _CLASS_GSTMINIOBJECT(Message, GstMessage, GST_MESSAGE, Gst::MiniObject, GstMiniObject)
  _IGNORE(gst_message_ref, gst_message_unref)
 public:
+
   /** Get the structure of a message.
-   * @return The Gst::Structure of the message (unmodifiable)
+   * @return The Gst::Structure of the message.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
 public:
   /** Wrap a GstMessage* in a C++ instance, creating an instance of a
Index: gstreamer/src/structure.hg
===================================================================
--- gstreamer/src/structure.hg	(revision 1494)
+++ gstreamer/src/structure.hg	(working copy)
@@ -45,26 +45,15 @@
  */
 class Structure
 {
-  _CLASS_BOXEDTYPE_NCOPY(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
-
+ _CLASS_BOXEDTYPE(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
 public:
-  /** For example,
-   * bool on_foreach(const Glib::QueryQuark& id, const Glib::ValueBase& value);
-   * The foreach function should return true if foreach operation should
-   * continue, false if operation should stop with false.
-   */
-  typedef sigc::slot<bool, const Glib::QueryQuark&, const Glib::ValueBase&> SlotForeach;
 
-  /** For example,
-   * bool on_map(const Glib::QueryQuark& id, Glib::ValueBase& value);
-   * The map function should return true if map operation should continue,
-   * false if operation should stop with false.
+  explicit Structure(const Glib::ustring& name);
+
+  /** Use this to discover if the Structure is a valid object.
    */
-  typedef sigc::slot<bool, const Glib::QueryQuark&, Glib::ValueBase&> SlotMap;
+  operator bool() const;
 
-public:
-  Structure(const Glib::ustring& name);
-
   _WRAP_METHOD(Glib::ustring get_name() const, gst_structure_get_name)
   _WRAP_METHOD(bool has_name(const Glib::ustring& name) const, gst_structure_has_name)
   _WRAP_METHOD(void set_name(const Glib::ustring& name), gst_structure_set_name)
@@ -92,6 +81,9 @@
    */
   Structure& set_field(const Glib::ustring& fieldname, const Glib::ValueBase& value);
 
+  //Only for use inside gstreamermm:
+  static void _set_gstructure_field(GstStructure* cstructure, const Glib::ustring& fieldname, const Glib::ValueBase& value);
+
   /** Removes the field with the given name. If the field with the given name
    * does not exist, the structure is unchanged. Returns this Gst::Structure
    * for continued setting convenience.
@@ -104,6 +96,13 @@
   _WRAP_METHOD(void remove_all_fields(), gst_structure_remove_all_fields)
   _WRAP_METHOD(GType get_field_type(const Glib::ustring& fieldname) const, gst_structure_get_field_type)
 
+  /** For example,
+   * bool on_foreach(const Glib::QueryQuark& id, const Glib::ValueBase& value);
+   * The foreach function should return true if foreach operation should
+   * continue, false if operation should stop with false.
+   */
+  typedef sigc::slot<bool, const Glib::QueryQuark&, const Glib::ValueBase&> SlotForeach;
+
   /** Calls the provided slot once for each field in the Gst::Structure. The
    * slot must not modify the fields. Also see map_in_place().
    *
@@ -229,6 +228,13 @@
    */
   bool get_fraction(const Glib::ustring& fieldname, Gst::Fraction& fraction) const;
 
+  /** For example,
+   * bool on_map(const Glib::QueryQuark& id, Glib::ValueBase& value);
+   * The map function should return true if map operation should continue,
+   * false if operation should stop with false.
+   */
+  typedef sigc::slot<bool, const Glib::QueryQuark&, Glib::ValueBase&> SlotMap;
+
   /** Calls the provided slot once for each field in the Gst::Structure. In
    * contrast to foreach(), the function may modify but not delete the fields.
    * The structure must be mutable.
@@ -239,7 +245,7 @@
    */
   bool map_in_place(const SlotMap& slot);
 
-  _WRAP_METHOD(Glib::ustring nth_field_name(guint index) const, gst_structure_nth_field_name)
+  _WRAP_METHOD(Glib::ustring get_nth_field_name(guint index) const, gst_structure_nth_field_name)
   _WRAP_METHOD(Glib::ustring to_string() const, gst_structure_to_string)
 
   static Structure create_from_string(const Glib::ustring& the_string);
Index: tools/m4/class_boxedtype_ncopy.m4
===================================================================
--- tools/m4/class_boxedtype_ncopy.m4	(revision 1494)
+++ tools/m4/class_boxedtype_ncopy.m4	(working copy)
@@ -1,241 +0,0 @@
-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 and
-dnl destruction of underlying gobject at wrapper destruction is flexible)
-
-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 the wrapper should destroy the underlying gobject or not
-   * when the wrapper is deleted.
-   * @param destroy whether or not the wrapper should destroy the underlying
-   * gobject when it is destroyed
-   */
-  void set_destroy(bool destroy);
-
-protected:
-  __CNAME__* gobject_;
-
-private:
-  bool destroy;
-
-private:
-_IMPORT(SECTION_CLASS2)
-')
-
Index: tools/m4/convert.m4
===================================================================
--- tools/m4/convert.m4	(revision 1494)
+++ tools/m4/convert.m4	(working copy)
@@ -2,5 +2,4 @@
 include(convert_glib.m4)
 include(convert_gst.m4)
 include(class_gstminiobject.m4)
-include(class_boxedtype_ncopy.m4)
 include(class_boxedtype_ncopy_extra.m4)
Index: tests/test-caps-structures.cc
===================================================================
--- tests/test-caps-structures.cc	(revision 1494)
+++ tests/test-caps-structures.cc	(working copy)
@@ -54,14 +54,19 @@
 
   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;
+    const Gst::Structure s = caps->get_structure(i);
+    if(s)
+    {
+      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;
+  const Gst::Structure structure = caps->get_structure(1);
+  if(structure)
+    std::cout << "Caps structure index 1 = " << structure.get_name() << std::endl;
 
   return 0;
 }
Index: tests/test-event-wrap.cc
===================================================================
--- tests/test-event-wrap.cc	(revision 1494)
+++ tests/test-event-wrap.cc	(working copy)
@@ -36,7 +36,9 @@
   std::cout << "event is a Gst::EventLatency: " << (bool)event_latency  << std::endl;
   std::cout << "event type name: '" << Gst::get_name(event->get_event_type()) << "'" << std::endl;
 
-  std::cout << "Event structure name: '" << event->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = event->get_structure();
+  if(structure)
+    std::cout << "Event structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }
Index: tests/test-message-wrap.cc
===================================================================
--- tests/test-message-wrap.cc	(revision 1494)
+++ tests/test-message-wrap.cc	(working copy)
@@ -40,7 +40,9 @@
   std::cout << "message is a Gst::MessageWarning: " << (bool)message_warning  << std::endl;
   std::cout << "message type name: '" << Gst::get_name(message->get_message_type()) << "'"  << std::endl;
 
-  std::cout << "Message structure name: '" << message->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = message->get_structure();
+  if(structure)
+    std::cout << "Message structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }
Index: tests/test-query-wrap.cc
===================================================================
--- tests/test-query-wrap.cc	(revision 1494)
+++ tests/test-query-wrap.cc	(working copy)
@@ -36,7 +36,9 @@
   std::cout << "query is a Gst::QueryPosition: " << (bool)query_position  << std::endl;
   std::cout << "query type name: '" << Gst::get_name(query->get_query_type()) << "'" << std::endl;
 
-  std::cout << "Query structure name: '" << query->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = query->get_structure();
+  if(structure)
+    std::cout << "Query structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }
Index: examples/element_link/element_link.cc
===================================================================
--- examples/element_link/element_link.cc	(revision 1496)
+++ examples/element_link/element_link.cc	(working copy)
@@ -20,7 +20,6 @@
  */
 
 #include <gstreamermm.h>
-#include <stdexcept>
 #include <iostream>
 
 int main(int argc, char** argv)
@@ -42,14 +41,14 @@
   // We must add the elements to the pipeline before linking them:
   pipeline->add(element_source)->add(element_filter)->add(element_sink);
 
-  // Link
+  // Link the elements together:
   try
   {
     element_source->link(element_filter)->link(element_sink);
   }
   catch(const std::runtime_error& error)
   {
-    std::cout << error.what() << std::endl;
+    std::cout << "Exception while linking: " << error.what() << std::endl;
   }
 
   return 0;
Index: examples/ogg_player_gtkmm/player_window.cc
===================================================================
--- examples/ogg_player_gtkmm/player_window.cc	(revision 1499)
+++ examples/ogg_player_gtkmm/player_window.cc	(working copy)
@@ -75,13 +75,14 @@
   m_open_button.signal_clicked().connect(
     sigc::mem_fun(*this, &PlayerWindow::on_button_open) );
 
-  // get the bus from the pipeline
+  // Add a bus watch to receive messages from pipeline's bus
   Glib::RefPtr<Gst::Bus> bus = main_pipeline->get_bus();
+  if(bus)
+  {
+    m_watch_id = bus->add_watch(
+      sigc::mem_fun( *this, &PlayerWindow::on_bus_message) );
+  }
 
-  // Add a bus watch to receive messages from pipeline's bus
-  m_watch_id = bus->add_watch(
-    sigc::mem_fun( *this, &PlayerWindow::on_bus_message) );
-
   m_progress_scale.set_sensitive(false);
   m_play_button.set_sensitive(false);
   m_pause_button.set_sensitive(false);
@@ -99,13 +100,16 @@
 // This function is used to receive asynchronous messages from main_pipeline's bus
 bool PlayerWindow::on_bus_message(const Glib::RefPtr<Gst::Bus>& /* bus */, const Glib::RefPtr<Gst::Message>& message)
 {
-  switch (message->get_message_type())
+  switch(message->get_message_type())
   {
     case Gst::MESSAGE_EOS:
+      //We reached the end of the file, so stop playing:
       on_button_stop();
       break;
     case Gst::MESSAGE_ERROR:
     {
+      //There was an error, so stop playing, 
+      //and output some information to stdout:
       Glib::RefPtr<Gst::MessageError> error_message =
         Glib::RefPtr<Gst::MessageError>::cast_dynamic(message);
       if(error_message)
@@ -144,11 +148,11 @@
   m_pause_button.show();
 
   // Call on_timeout function at a 200ms
-  // interval to regularly update the position of the stream
+  // interval to regularly update the position of the stream:
   m_progress_connection = Glib::signal_timeout().connect(
     sigc::mem_fun(*this, &PlayerWindow::on_timeout), 200);
 
-  // set Gstmm pipeline to play mode
+  // Set the pipeline to play mode:
   m_main_pipeline->set_state(Gst::STATE_PLAYING);
 }
  
@@ -160,10 +164,10 @@
   m_pause_button.hide();
   m_play_button.show();
 
-  // disconnect progress callback
+  // Disconnect progress callback:
   m_progress_connection.disconnect();
   
-  // set Gstmm pipeline to pause mode
+  // Set the pipeline to pause mode:
   m_main_pipeline->set_state(Gst::STATE_PAUSED);
 }
  
@@ -180,10 +184,10 @@
   m_pause_button.hide();
   m_play_button.show();
 
-  // disconnect progress callback
+  // Disconnect progress callback:
   m_progress_connection.disconnect();
 
-  // set Gstmm pipeline to inactive mode
+  // Set the pipeline to inactive mode:
   m_main_pipeline->set_state(Gst::STATE_NULL);
   display_label_progress(0, m_duration);
   m_progress_scale.set_value(0);
@@ -191,45 +195,45 @@
 
 bool PlayerWindow::on_scale_value_changed(Gtk::ScrollType /* type_not_used */, double value)
 {
-  gint64 newPos = gint64(value * m_duration);
+  const gint64 new_pos = gint64(value * m_duration);
 
-  if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+  if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, new_pos))
   {
-    display_label_progress(newPos, m_duration);
+    display_label_progress(new_pos, m_duration);
     return true;
   }
   else
   {
-    std::cerr << "Could not seek!" << std::endl;
+    std::cerr << "Could not seek." << std::endl;
     return false;
   }
 }
 
 void PlayerWindow::on_button_rewind()
 {
-  static const gint64 skipAmount = GST_SECOND * 2;
+  static const gint64 skip_amount = GST_SECOND * 2;
 
   gint64 pos = 0;
   Gst::Format fmt = Gst::FORMAT_TIME;
 
   if(m_main_pipeline->query_position(fmt, pos))
   {
-    const gint64 newPos = (pos > skipAmount) ? (pos - skipAmount) : 0;
+    const gint64 new_pos = (pos > skip_amount) ? (pos - skip_amount) : 0;
 
-    if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+    if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, new_pos))
     {
-      display_label_progress(newPos, m_duration);
-      m_progress_scale.set_value(double(newPos) / m_duration);
+      display_label_progress(new_pos, m_duration);
+      m_progress_scale.set_value(double(new_pos) / m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
 void PlayerWindow::on_button_forward()
 {
   //TODO: Wrap GST_SECOND:
-  static const gint64 skipAmount = GST_SECOND * 3;
+  static const gint64 skip_amount = GST_SECOND * 3;
 
   gint64 pos = 0;
   Gst::Format fmt = Gst::FORMAT_TIME;
@@ -243,11 +247,11 @@
 
     posQuery->parse(fmt, pos);
 
-    gint64 newPos = ((pos + skipAmount) < m_duration) ? (pos + skipAmount) :
-      m_duration;
+    const gint64 new_pos =
+      ((pos + skip_amount) < m_duration) ? (pos + skip_amount) : m_duration;
 
     Glib::RefPtr<Gst::Event> event = Gst::EventSeek::create(1.0, fmt,
-      Gst::SEEK_FLAG_FLUSH, Gst::SEEK_TYPE_SET, newPos,
+      Gst::SEEK_FLAG_FLUSH, Gst::SEEK_TYPE_SET, new_pos,
       Gst::SEEK_TYPE_NONE, -1);
 
     Glib::RefPtr<Gst::EventSeek> seekEvent =
@@ -255,11 +259,11 @@
 
     if(m_main_pipeline->send_event(seekEvent))
     {
-      m_progress_scale.set_value(double(newPos) / m_duration);
-      display_label_progress(newPos, m_duration);
+      m_progress_scale.set_value(double(new_pos) / m_duration);
+      display_label_progress(new_pos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
@@ -314,21 +318,21 @@
 void PlayerWindow::display_label_progress(gint64 pos, gint64 len)
 {
   std::ostringstream locationStream(std::ostringstream::out);
-  std::ostringstream durationStream(std::ostringstream::out);
-
   locationStream << std::right << std::setfill('0') << 
     std::setw(3) << Gst::get_hours(pos) << ":" <<
     std::setw(2) << Gst::get_minutes(pos) << ":" <<
     std::setw(2) << Gst::get_seconds(pos) << "." <<
     std::setw(9) << std::left << Gst::get_fractional_seconds(pos);
 
+  std::ostringstream durationStream(std::ostringstream::out);
   durationStream << std::right << std::setfill('0') <<
     std::setw(3) << Gst::get_hours(len) << ":" <<
     std::setw(2) << Gst::get_minutes(len) << ":" <<
     std::setw(2) << Gst::get_seconds(len) << "." <<
     std::setw(9) << std::left << Gst::get_fractional_seconds(len);
 
-  m_progress_label.set_text(locationStream.str() + " / " + durationStream.str());
+  m_progress_label.set_text(
+    locationStream.str() + " / " + durationStream.str() );
 }
 
 PlayerWindow::~PlayerWindow()
Index: examples/ogg_player_gtkmm/main.cc
===================================================================
--- examples/ogg_player_gtkmm/main.cc	(revision 1497)
+++ examples/ogg_player_gtkmm/main.cc	(working copy)
@@ -33,9 +33,17 @@
 
 void on_parser_pad_added(const Glib::RefPtr<Gst::Pad>& newPad)
 {
-  // We can now link this pad with the audio decoder
+  // We can now link this pad with the audio decoder.
   Glib::RefPtr<Gst::Pad> sinkPad = decoder->get_pad("sink");
-  newPad->link(sinkPad);
+
+  try
+  {
+    newPad->link(sinkPad);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cerr << "Exception caught while linking: " << ex.what() << std::endl;
+  }
 }
 
 int
@@ -50,26 +58,47 @@
   // Create the elements
   // Reads file from disk
   Glib::RefPtr<Gst::Element> source = Gst::ElementFactory::create_element("filesrc");
+  if(!source)
+  {
+    std::cerr << "filesrc element could not be created" << std::endl;
+    return -1;
+  }
 
   // Parses the ogg streams into elementary streams (note that an ogg file may contain a video stream too)
   Glib::RefPtr<Gst::Element> parser = Gst::ElementFactory::create_element("oggdemux");
+  if(!parser)
+  {
+    std::cerr << "oggdemux element could not be created" << std::endl;
+    return -1;
+  }
 
   // Decodes a vorbis stream
-  decoder = Gst::ElementFactory::create_element("vorbisdec", "vorbis-decoder");
+  decoder = Gst::ElementFactory::create_element("vorbisdec");
+  if(!decoder)
+  {
+    std::cerr << "vorbisdec element could not be created" << std::endl;
+    return -1;
+  }
 
-  // Converts audio() to a format which can be used by the next element
+  // Converts audio to a format which can be used by the next element
   Glib::RefPtr<Gst::Element> conv = Gst::ElementFactory::create_element("audioconvert");
+  if(!conv)
+  {
+    std::cerr << "audioconvert element could not be created" << std::endl;
+    return -1;
+  }
 
   // Outputs sound to an ALSA audio device
   Glib::RefPtr<Gst::Element> sink = Gst::ElementFactory::create_element("alsasink");
-
-  if (!pipeline || !source || !parser || !decoder || !conv || !sink)
+  if(!sink)
   {
-    std::cerr << "One element could not be created" << std::endl;
+    std::cerr << "sink element could not be created" << std::endl;
     return -1;
   }
 
+
   // Put all elements in a pipeline:
+  // TODO: Bin::add() does not actually throw an exception. It probably should.
   try
   {
     pipeline->add(source)->add(parser)->add(decoder)->add(conv)->add(sink);
@@ -80,18 +109,26 @@
     return -1;
   }
 
-  // Link together:
-  source->link(parser);
 
-  // We cannot link the parser and decoder yet, 
-  // because the parser uses dynamic pads. For that,
-  // we set a pad-added signal handler:
-  parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
+  // Link the elements together:
+  try
+  {
+    source->link(parser);
 
-  decoder->link(conv)->link(sink);
+    // We cannot link the parser and decoder yet, 
+    // because the parser uses dynamic pads.
+    // So we do it later in a pad-added signal handler:
+    parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
 
+    decoder->link(conv)->link(sink);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cout << "Exception while linking elements: " << ex.what() << std::endl;
+  }
+
+  // Create our window and show it:
   PlayerWindow mainWindow(source, pipeline);
-
   kit.run(mainWindow);
 
   // Clean up nicely:
Index: examples/ogg_player/main.cc
===================================================================
--- examples/ogg_player/main.cc	(revision 1498)
+++ examples/ogg_player/main.cc	(working copy)
@@ -101,7 +101,15 @@
   // We can now link this pad with the audio decoder
   std::cout << "Dynamic pad created. Linking parser/decoder." << std::endl;
   Glib::RefPtr<Gst::Pad> sinkPad = decoder->get_pad("sink");
-  newPad->link(sinkPad);
+
+  try
+  {
+    newPad->link(sinkPad);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cerr << "Exception caught while linking: " << ex.what() << std::endl;
+  }
 }
 
 bool on_sink_pad_have_data(const Glib::RefPtr<Gst::Pad>& pad,
@@ -181,7 +189,8 @@
   Glib::RefPtr<Gst::Bus> bus = pipeline->get_bus();
   bus->add_watch( sigc::ptr_fun(&on_bus_message) );
 
-  // Put all the elements in a pipeline, linked to each other:
+
+  // Put all the elements in a pipeline:
   try
   {
     pipeline->add(source)->add(parser)->add(decoder)->add(conv)->add(sink);
@@ -192,22 +201,30 @@
     return -1;
   }
 
-  // Link together:
-  // TODO: Why isn't this done during add()?:
-  source->link(parser);
 
-  // We cannot link the parser and decoder yet, 
-  // because the parser uses dynamic pads. For that,
-  // we set a pad-added signal handler:
-  parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
+  // Link the elements together:
+  try
+  {
+    source->link(parser);
 
-  decoder->link(conv)->link(sink);
+    // We cannot link the parser and decoder yet, 
+    // because the parser uses dynamic pads.
+    // So we do it later in a pad-added signal handler:
+    parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
 
+    decoder->link(conv)->link(sink);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cout << "Exception while linking elements: " << ex.what() << std::endl;
+  }
+
+
   // Call on_timeout function at a 200ms
   // interval to regularly print the position of the stream
   Glib::signal_timeout().connect(sigc::ptr_fun(&on_timeout), 200);
 
-  // Now set to playing and start the main loop:
+  // Now set the whole pipeline to playing and start the main loop:
   std::cout << "Setting to PLAYING." << std::endl;
   pipeline->set_state(Gst::STATE_PLAYING);
   std::cout << "Running." << std::endl;
Index: examples/media_player_gtkmm/player_window.cc
===================================================================
--- examples/media_player_gtkmm/player_window.cc	(revision 1499)
+++ examples/media_player_gtkmm/player_window.cc	(working copy)
@@ -117,7 +117,7 @@
   if(message->get_message_type() != Gst::MESSAGE_ELEMENT)
     return Gst::BUS_PASS;
 
-  if(!message->get_structure()->has_name("prepare-xwindow-id"))
+  if(!message->get_structure().has_name("prepare-xwindow-id"))
      return Gst::BUS_PASS;
 
   Glib::RefPtr<Gst::Element> element =
@@ -177,16 +177,24 @@
   Glib::RefPtr<Gst::Buffer> buffer = Glib::RefPtr<Gst::Buffer>::cast_dynamic(data);
 
   if(buffer) {
-    Glib::Value<int> widthValue;
-    Glib::Value<int> heightValue;
+    Glib::Value<int> width_value;
+    Glib::Value<int> height_value;
 
     Glib::RefPtr<Gst::Caps> caps = buffer->get_caps();
-    caps->get_structure(0)->get_field("width", widthValue);
-    caps->get_structure(0)->get_field("height", heightValue);
 
-    m_video_area.set_size_request(widthValue.get(), heightValue.get());
-    resize(1, 1);     // Resize to minimum when first playing by making size
-    check_resize();   // smallest then resizing according to video new size
+    const Gst::Structure structure = caps->get_structure(0);
+    if(structure)
+    {
+      structure.get_field("width", width_value);
+      structure.get_field("height", height_value);
+    }
+
+    m_video_area.set_size_request(width_value.get(), height_value.get());
+
+    // Resize to minimum when first playing by making size 
+    // smallest then resizing according to video new size:
+    resize(1, 1);
+    check_resize();
   }
 
   pad->remove_buffer_probe(m_pad_probe_id);
@@ -277,7 +285,7 @@
   }
   else
   {
-    std::cerr << "Could not seek!" << std::endl;
+    std::cerr << "Could not seek." << std::endl;
     return false;
   }
 }
@@ -298,7 +306,7 @@
       display_label_progress(newPos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
@@ -334,7 +342,7 @@
       display_label_progress(newPos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 


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