Re: Completed what I can in gstreamermm
- From: Murray Cumming <murrayc murrayc com>
- To: José Alburquerque <jaalburquerque cox net>
- Cc: gtkmm-list gnome org
- Subject: Re: Completed what I can in gstreamermm
- Date: Sat, 17 May 2008 22:39:15 +0200
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]