|
View:
New views
13 Messages
—
Rating Filter:
Alert me
|
|
|
Completed what I can in gstreamermmI thought you'd all like to know that I've done all I think I can do for
gstreamermm to the best of my ability. I didn't get a chance to look at Gst::Iterator, complete the docs and wrap Gst::TagLIst, Gst::TagSetter or any of http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/ and http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/ (except GstBase::XOverlay) because time did not allow. But I really feel I've done quite a bit and my time will be really limited in the future so I will not be able to dedicate more time. 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. -- José Alburquerque jaalburquerque@... The path to real wisdom begins with a deep loving respect for the ever living God (Prov. 1:7) _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmOn Thu, 2008-05-01 at 09:10 -0400, José Alburquerque wrote:
> I thought you'd all like to know that I've done all I think I can do for > gstreamermm to the best of my ability. I didn't get a chance to look at > Gst::Iterator, complete the docs and wrap Gst::TagLIst, Gst::TagSetter > or any of > http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/ > and > http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/ > (except GstBase::XOverlay) because time did not allow. But I really > feel I've done quite a bit and my time will be really limited in the > future so I will not be able to dedicate more time. > > 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'll take a look during some train journeys that I will be making over the next few days and see if I can add some improvements of my own. -- murrayc@... www.murrayc.com www.openismus.com _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmMurray Cumming wrote:
> On Thu, 2008-05-01 at 09:10 -0400, José Alburquerque wrote: > >> I thought you'd all like to know that I've done all I think I can do for >> gstreamermm to the best of my ability. I didn't get a chance to look at >> Gst::Iterator, complete the docs and wrap Gst::TagLIst, Gst::TagSetter >> or any of >> http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/ >> and >> http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/ >> (except GstBase::XOverlay) because time did not allow. But I really >> feel I've done quite a bit and my time will be really limited in the >> future so I will not be able to dedicate more time. >> >> 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. > > Glad I could help. > I'll take a look during some train journeys that I will be making over > the next few days and see if I can add some improvements of my own. > > Please do and please don't hesitate to ask about anything while I take care of a few urgent matters. Take care. -- José Alburquerque jaalburquerque@... The path to real wisdom begins with a deep loving respect for the ever living God (Prov. 1:7) _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmJosé Alburquerque wrote:
> Murray Cumming wrote: > >> On Thu, 2008-05-01 at 09:10 -0400, José Alburquerque wrote: >> >> >>> I thought you'd all like to know that I've done all I think I can do for >>> gstreamermm to the best of my ability. I didn't get a chance to look at >>> Gst::Iterator, complete the docs and wrap Gst::TagLIst, Gst::TagSetter >>> or any of >>> http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/ >>> and >>> http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/ >>> (except GstBase::XOverlay) because time did not allow. But I really >>> feel I've done quite a bit and my time will be really limited in the >>> future so I will not be able to dedicate more time. >>> >>> 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. >> >> >> > > Glad I could help. > > 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. :-) -Jose >> I'll take a look during some train journeys that I will be making over >> the next few days and see if I can add some improvements of my own. >> >> >> > Please do and please don't hesitate to ask about anything while I take > care of a few urgent matters. Take care. > > -- José Alburquerque jaalburquerque@... The path to real wisdom begins with a deep loving respect for the ever living God (Prov. 1:7) _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmOn 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. :-) 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@... www.murrayc.com www.openismus.com [gstmm_structure_by_value.patch] Index: ChangeLog =================================================================== --- ChangeLog (revision 1500) +++ ChangeLog (working copy) @@ -1,6 +1,53 @@ 2008-05-17 Murray Cumming <murrayc@...> + * 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@...> + + * 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@...> + + * 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; } } _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmMurray Cumming wrote:
> 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(). > > An obviously useful logical change. :-) Changes like these will not affect my application development because I understand that gstreamermm is still in early development so I'm happy to adjust my project development accordingly while gstreamermm stabilizes. > 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. > > To be honest, I haven't begun to use gstreamermm enough yet in my project for this change to affect me yet, but looking at it more closely, there was an error in my logic. I was trying to ensure that if someone tried to modify a Gst::Structure of a Gst::Caps obtained with Gst::Caps::get_structure() the change would be reflected in the actual Gst::Structure of the Gst::Caps as in the following: ... Gst::Structure structure = caps->get_structure(0); if (structure) { Glib::Value<int> width; width.init(Glib::Value<int>::value_type()); width.set(300); structure.set_field("width", width); } ... I had unfortunately overlooked that the GstCaps docs say that GstStructures of GstCaps should not be modified if obtained with gst_caps_get_structure(const GstCaps*, guint index) <http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-GstCaps.html#gst-caps-get-structure>. What you're doing is best and if I had been more careful reading the docs, I would not have made these changes to Gst::Structure. > I might need to do something similar for TagList. > > As you say, TagList should undergo the same changes. BTW, I had taken a look at your commits of last week and noticed some TODO's that I might have quickly been able to do (time notwithstanding) but I could not because I was affected by the svn+ssh bug. I'm still a bit pressed for time, but if I find time here and there, would it be alright if I commit some light stuff also? -- José Alburquerque jaalburquerque@... The path to real wisdom begins with a deep loving respect for the ever living God (Prov. 1:7) _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermmOn Sat, 2008-05-17 at 23:58 -0400, José Alburquerque wrote:
> would it be > alright if I commit some light stuff also? Of course. I consider you the maintainer really. -- Murray Cumming murrayc@... www.murrayc.com www.openismus.com _______________________________________________ gtkmm-list mailing list gtkmm-list@... http://mail.gnome.org/mailman/listinfo/gtkmm-list |
|
|
Re: Completed what I can in gstreamermm |