[gstreamermm] Message: Modify create() method so that wrappers are not leaked.
- From: José Alburquerque <jaalburqu src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gstreamermm] Message: Modify create() method so that wrappers are not leaked.
- Date: Mon, 8 Feb 2010 04:46:52 +0000 (UTC)
commit 043fe17814f21fe05aae9af7146b8baffd90a172
Author: José Alburquerque <jaalburqu svn gnome org>
Date: Sun Feb 7 23:21:47 2010 -0500
Message: Modify create() method so that wrappers are not leaked.
* gstreamer/src/message.ccg:
* gstreamer/src/message.hg: Wrapped the finalize virtual function of
GstMiniObject. Modified the create() method so that the C++ wrapper
is stored in the structure of the message. Hooked into the
GstMiniObject finalize virtual function so that wrappers can be
deleted before final message destruction.
* gstreamer/src/gst_vfuncs.defs: Defined GstMessage finalize vfunc.
Partly fixes bug #608702 (Massimiliano).
ChangeLog | 14 ++
gstreamer/src/gst_vfuncs.defs | 7 +
gstreamer/src/message.ccg | 304 +++++++++++++++++++++++++++--------------
gstreamer/src/message.hg | 21 +++-
4 files changed, 238 insertions(+), 108 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 265789a..de06ead 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2010-02-07 José Alburquerque <jaalburqu svn gnome org>
+
+ Message: Modify create() method so that wrappers are not leaked.
+
+ * gstreamer/src/message.ccg:
+ * gstreamer/src/message.hg: Wrapped the finalize virtual function of
+ GstMiniObject. Modified the create() method so that the C++ wrapper
+ is stored in the structure of the message. Hooked into the
+ GstMiniObject finalize virtual function so that wrappers can be
+ deleted before final message destruction.
+ * gstreamer/src/gst_vfuncs.defs: Defined GstMessage finalize vfunc.
+
+ Partly fixes bug #608702 (Massimiliano).
+
2010-02-04 José Alburquerque <jaalburqu svn gnome org>
MiniObject: Lay the foundation for virtual methods in derived classes.
diff --git a/gstreamer/src/gst_vfuncs.defs b/gstreamer/src/gst_vfuncs.defs
index 23333f3..7d1763b 100644
--- a/gstreamer/src/gst_vfuncs.defs
+++ b/gstreamer/src/gst_vfuncs.defs
@@ -755,6 +755,13 @@
)
)
+; GstMessage
+
+(define-vfunc finalize
+ (of-object "GstMessage")
+ (return-type "void")
+)
+
; GstMixer
(define-vfunc list_tracks
diff --git a/gstreamer/src/message.ccg b/gstreamer/src/message.ccg
index 61337e6..6a03940 100644
--- a/gstreamer/src/message.ccg
+++ b/gstreamer/src/message.ccg
@@ -961,129 +961,223 @@ Glib::RefPtr<Gst::Element> MessageStreamStatus::parse_owner() const
return Glib::wrap(gst_element, true);
}
+namespace
+{
+
+static GstMiniObjectFinalizeFunction original_gst_message_finalize_function = 0;
+
+static void gstreamermm_gst_message_finalize_hook_function(GstMiniObject* mini_object)
+{
+ gpointer wrapper = 0;
+
+ GstStructure* structure = const_cast<GstStructure*>(
+ gst_message_get_structure(GST_MESSAGE(mini_object)));
+
+ if(structure && gst_structure_get(structure, "cpp_wrapper", G_TYPE_POINTER,
+ &wrapper, static_cast<void*>(0)))
+ {
+ gst_structure_remove_field(structure, "cpp_wrapper");
+ // An extra ref is needed for the unref in the Gst::MiniObject destructor.
+ gst_mini_object_ref(mini_object);
+ delete static_cast<Gst::Message*>(wrapper);
+ }
+
+ // Call the original finalize function.
+ original_gst_message_finalize_function(mini_object);
+}
+
+}
+
Glib::RefPtr<Gst::Message> Message::wrap(GstMessage* message, bool take_copy)
{
+ Gst::Message* wrapper = 0;
Glib::RefPtr<Gst::Message> result;
if(!message)
return result;
- if(gst_mixer_message_get_type(message) == GST_MIXER_MESSAGE_INVALID)
+ // Attempt to get an existing wrapper before creating a new one. The
+ // current wrapper is stored in the GstStructure of the message. If the
+ // message does not have a structure (some don't), it is given one in which
+ // the wrapper can be stored.
+
+ GstStructure* structure =
+ const_cast<GstStructure*>(gst_message_get_structure(message));
+
+ if(!structure)
{
- switch(GST_MESSAGE_TYPE(message))
- {
- case GST_MESSAGE_EOS:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageEos(message) );
- break;
- case GST_MESSAGE_ERROR:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageError(message) );
- break;
- case GST_MESSAGE_WARNING:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageWarning(message) );
- break;
- case GST_MESSAGE_INFO:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageInfo(message) );
- break;
- case GST_MESSAGE_TAG:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageTag(message) );
- break;
- case GST_MESSAGE_BUFFERING:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageBuffering(message) );
- break;
- case GST_MESSAGE_STATE_CHANGED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStateChanged(message) );
- break;
- case GST_MESSAGE_STATE_DIRTY:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStateDirty(message) );
- break;
- case GST_MESSAGE_STEP_DONE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStepDone(message) );
- break;
- case GST_MESSAGE_CLOCK_PROVIDE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageClockProvide(message) );
- break;
- case GST_MESSAGE_CLOCK_LOST:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageClockLost(message) );
- break;
- case GST_MESSAGE_NEW_CLOCK:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageNewClock(message) );
- break;
- case GST_MESSAGE_APPLICATION:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageApplication(message) );
- break;
- case GST_MESSAGE_ELEMENT:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageElement(message) );
- break;
- case GST_MESSAGE_SEGMENT_START:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageSegmentStart(message) );
- break;
- case GST_MESSAGE_SEGMENT_DONE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageSegmentDone(message) );
- break;
- case GST_MESSAGE_DURATION:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageDuration(message) );
- break;
- case GST_MESSAGE_LATENCY:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageLatency(message) );
- break;
- case GST_MESSAGE_ASYNC_START:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageAsyncStart(message) );
- break;
- case GST_MESSAGE_ASYNC_DONE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageAsyncDone(message) );
- break;
- case GST_MESSAGE_STEP_START:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStepStart(message) );
- break;
- case GST_MESSAGE_STRUCTURE_CHANGE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStructureChange(message) );
- break;
- case GST_MESSAGE_REQUEST_STATE:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageRequestState(message) );
- break;
- case GST_MESSAGE_STREAM_STATUS:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageStreamStatus(message) );
- break;
- case GST_MESSAGE_UNKNOWN:
- case GST_MESSAGE_ANY:
- result = Gst::wrap(message, false);
- break;
- /* The rest of the message types are custom ones */
- default:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageCustom(message) );
- }
+ // Add a structure to a message that does not have one. The lines are
+ // adapted from gst_message_new_custom().
+ structure = gst_structure_empty_new("wrapper");
+ gst_structure_set_parent_refcount (structure, &message->mini_object.refcount);
+ message->structure = structure;
}
- else
+
+ gst_structure_get(structure, "cpp_wrapper", G_TYPE_POINTER, &wrapper,
+ static_cast<void*>(0));
+
+ if(!wrapper)
{
- switch(GST_MESSAGE_TYPE(message))
+ // In this case there is no pre-existing wrapper so create one which will
+ // then be stored for later usage and then deletion on message
+ // finalization.
+ if(gst_mixer_message_get_type(message) == GST_MIXER_MESSAGE_INVALID)
+ {
+ switch(GST_MESSAGE_TYPE(message))
+ {
+ case GST_MESSAGE_EOS:
+ wrapper = new Gst::MessageEos(message);
+ break;
+ case GST_MESSAGE_ERROR:
+ wrapper = new Gst::MessageError(message);
+ break;
+ case GST_MESSAGE_WARNING:
+ wrapper = new Gst::MessageWarning(message);
+ break;
+ case GST_MESSAGE_INFO:
+ wrapper = new Gst::MessageInfo(message);
+ break;
+ case GST_MESSAGE_TAG:
+ wrapper = new Gst::MessageTag(message);
+ break;
+ case GST_MESSAGE_BUFFERING:
+ wrapper = new Gst::MessageBuffering(message);
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ wrapper = new Gst::MessageStateChanged(message);
+ break;
+ case GST_MESSAGE_STATE_DIRTY:
+ wrapper = new Gst::MessageStateDirty(message);
+ break;
+ case GST_MESSAGE_STEP_DONE:
+ wrapper = new Gst::MessageStepDone(message);
+ break;
+ case GST_MESSAGE_CLOCK_PROVIDE:
+ wrapper = new Gst::MessageClockProvide(message);
+ break;
+ case GST_MESSAGE_CLOCK_LOST:
+ wrapper = new Gst::MessageClockLost(message);
+ break;
+ case GST_MESSAGE_NEW_CLOCK:
+ wrapper = new Gst::MessageNewClock(message);
+ break;
+ case GST_MESSAGE_APPLICATION:
+ wrapper = new Gst::MessageApplication(message);
+ break;
+ case GST_MESSAGE_ELEMENT:
+ wrapper = new Gst::MessageElement(message);
+ break;
+ case GST_MESSAGE_SEGMENT_START:
+ wrapper = new Gst::MessageSegmentStart(message);
+ break;
+ case GST_MESSAGE_SEGMENT_DONE:
+ wrapper = new Gst::MessageSegmentDone(message);
+ break;
+ case GST_MESSAGE_DURATION:
+ wrapper = new Gst::MessageDuration(message);
+ break;
+ case GST_MESSAGE_LATENCY:
+ wrapper = new Gst::MessageLatency(message);
+ break;
+ case GST_MESSAGE_ASYNC_START:
+ wrapper = new Gst::MessageAsyncStart(message);
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ wrapper = new Gst::MessageAsyncDone(message);
+ break;
+ case GST_MESSAGE_STEP_START:
+ wrapper = new Gst::MessageStepStart(message);
+ break;
+ case GST_MESSAGE_STRUCTURE_CHANGE:
+ wrapper = new Gst::MessageStructureChange(message);
+ break;
+ case GST_MESSAGE_REQUEST_STATE:
+ wrapper = new Gst::MessageRequestState(message);
+ break;
+ case GST_MESSAGE_STREAM_STATUS:
+ wrapper = new Gst::MessageStreamStatus(message);
+ break;
+ case GST_MESSAGE_UNKNOWN:
+ case GST_MESSAGE_ANY:
+ wrapper = new Gst::Message(message);
+ break;
+ /* The rest of the message types are custom ones */
+ default:
+ wrapper = new Gst::MessageCustom(message);
+ }
+ }
+ else
{
- case GST_MIXER_MESSAGE_MUTE_TOGGLED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerMuteToggled(message) );
- break;
- case GST_MIXER_MESSAGE_RECORD_TOGGLED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerRecordToggled(message) );
- break;
- case GST_MIXER_MESSAGE_VOLUME_CHANGED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerVolumeChanged(message) );
- break;
- case GST_MIXER_MESSAGE_OPTION_CHANGED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerOptionChanged(message) );
- break;
- case GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerOptionsListChanged(message) );
- break;
- case GST_MIXER_MESSAGE_MIXER_CHANGED:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageMixerChanged(message) );
- break;
- default:
- result = Glib::RefPtr<Gst::Message>( new Gst::MessageCustom(message) );
+ switch(GST_MESSAGE_TYPE(message))
+ {
+ case GST_MIXER_MESSAGE_MUTE_TOGGLED:
+ wrapper = new Gst::MessageMixerMuteToggled(message);
+ break;
+ case GST_MIXER_MESSAGE_RECORD_TOGGLED:
+ wrapper = new Gst::MessageMixerRecordToggled(message);
+ break;
+ case GST_MIXER_MESSAGE_VOLUME_CHANGED:
+ wrapper = new Gst::MessageMixerVolumeChanged(message);
+ break;
+ case GST_MIXER_MESSAGE_OPTION_CHANGED:
+ wrapper = new Gst::MessageMixerOptionChanged(message);
+ break;
+ case GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED:
+ wrapper = new Gst::MessageMixerOptionsListChanged(message);
+ break;
+ case GST_MIXER_MESSAGE_MIXER_CHANGED:
+ wrapper = new Gst::MessageMixerChanged(message);
+ break;
+ default:
+ wrapper = new Gst::MessageCustom(message);
+ }
}
+
+ // Store the current wrapper in the structure of the message.
+ gst_structure_set(structure, "cpp_wrapper", G_TYPE_POINTER, wrapper,
+ static_cast<void*>(0));
}
+ result = Glib::RefPtr<Gst::Message>(wrapper);
+
if(result && take_copy)
result->reference();
+ // Hook into the GstMessage finalize function.
+ if(!original_gst_message_finalize_function)
+ {
+ original_gst_message_finalize_function =
+ GST_MINI_OBJECT_GET_CLASS(message)->finalize;
+
+ GST_MINI_OBJECT_GET_CLASS(message)->finalize =
+ gstreamermm_gst_message_finalize_hook_function;
+ }
+
return result;
}
+#ifdef GLIBMM_VFUNCS_ENABLED
+void Message_Class::finalize_vfunc_callback(GstMiniObject* self)
+{
+ BaseClassType *const base = static_cast<BaseClassType*>(
+ g_type_class_peek_parent(GST_MINI_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
+ );
+
+ // Call the original underlying C function:
+ if(base && GST_MINI_OBJECT_CLASS(base)->finalize)
+ (*GST_MINI_OBJECT_CLASS(base)->finalize)(self);
+
+}
+void Message::finalize_vfunc()
+{
+ BaseClassType *const base = static_cast<BaseClassType*>(
+ g_type_class_peek_parent(G_OBJECT_GET_CLASS(gobj())) // Get the parent class of the object class (The original underlying C class).
+ );
+
+ if(base && GST_MINI_OBJECT_CLASS(base)->finalize)
+ (*GST_MINI_OBJECT_CLASS(base)->finalize)(GST_MINI_OBJECT(gobj()));
+}
+#endif //GLIBMM_VFUNCS_ENABLED
+
+
} //namespace Gst
diff --git a/gstreamer/src/message.hg b/gstreamer/src/message.hg
index 4e1155b..64d2a06 100644
--- a/gstreamer/src/message.hg
+++ b/gstreamer/src/message.hg
@@ -73,9 +73,9 @@ class TagList;
*/
class Message : public Gst::MiniObject
{
-protected:
- _CLASS_GSTMINIOBJECT(Message, GstMessage, GST_MESSAGE, Gst::MiniObject, GstMiniObject)
- _IGNORE(gst_message_ref, gst_message_unref)
+ _CLASS_GSTMINIOBJECT(Message, GstMessage, GST_MESSAGE, Gst::MiniObject, GstMiniObject)
+ _IGNORE(gst_message_ref, gst_message_unref)
+
public:
/** Wrap a GstMessage* in a C++ instance, creating an instance of a
* derived Gst::Message. Gst::wrap() would just create a Gst::Message
@@ -109,6 +109,21 @@ public:
/** Get the object that posted the message.
*/
_MEMBER_GET_GOBJECT(source, src, Gst::Object, GstObject*)
+
+#ifdef GLIBMM_VFUNCS_ENABLED
+ /** Virtual function called when the Gst::Message is about to be finalized.
+ */
+ virtual void finalize_vfunc();
+#endif //GLIBMM_VFUNCS_ENABLED
+
+protected:
+#m4begin
+ _PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
+ GST_MINI_OBJECT_CLASS(klass)->finalize = &finalize_vfunc_callback;
+ _SECTION(SECTION_PH_VFUNCS)
+ static void finalize_vfunc_callback(GstMiniObject* self);
+ _POP()
+#m4end
};
//TODO: Modify create methods of derived Message classes to return
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]