context: Add gst_context_writable_structure() and let get_structure() return const...
[platform/upstream/gstreamer.git] / gst / gstcontext.c
1 /* GStreamer
2  * Copyright (C) 2013 Collabora Ltd.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  *
5  * gstcontext.h: Header for GstContext subsystem
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gstcontext
25  * @short_description: Lightweight objects to represent element contexts
26  * @see_also: #GstMiniObject, #GstElement
27  *
28  * #GstContext is a container object used to store contexts like a device
29  * context, a display server connection and similar concepts that should
30  * be shared between multiple elements.
31  *
32  * Applications can set a context on a complete pipeline by using
33  * gst_element_set_context(), which will then be propagated to all
34  * child elements. Elements can handle these in GstElement::set_context()
35  * and merge them with the context information they already have.
36  *
37  * When an element needs a context it will do the following actions in this
38  * order until one step succeeds:
39  * 1) Check if the element already has a context
40  * 2) Query downstream with GST_QUERY_CONTEXT for the context
41  * 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required
42  *    context types and afterwards check if a usable context was set now
43  * 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
44  *    and send a GST_EVENT_CONTEXT event downstream, containing the complete
45  *    context information at this time.
46  *
47  * Applications should catch the GST_MESSAGE_HAVE_CONTEXT messages and remember
48  * any content from it unless it has a custom version of a specific context. If
49  * later an element is posting a GST_MESSAGE_NEED_CONTEXT message for a specific
50  * context that was created by an element before the application should pass it
51  * to the complete pipeline.
52  *
53  * Since: 1.2
54  */
55
56 #include "gst_private.h"
57 #include <string.h>
58 #include "gstcontext.h"
59 #include "gstquark.h"
60
61 struct _GstContext
62 {
63   GstMiniObject mini_object;
64
65   GstStructure *structure;
66 };
67
68 #define GST_CONTEXT_STRUCTURE(c)  (((GstContext *)(c))->structure)
69
70 static GType _gst_context_type = 0;
71 GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
72
73 void
74 _priv_gst_context_initialize (void)
75 {
76   GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts");
77
78   /* the GstMiniObject types need to be class_ref'd once before it can be
79    * done from multiple threads;
80    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
81   gst_context_get_type ();
82
83   _gst_context_type = gst_context_get_type ();
84 }
85
86 static void
87 _gst_context_free (GstContext * context)
88 {
89   GstStructure *structure;
90
91   g_return_if_fail (context != NULL);
92
93   GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT,
94       context, GST_CONTEXT_STRUCTURE (context));
95
96   structure = GST_CONTEXT_STRUCTURE (context);
97   if (structure) {
98     gst_structure_set_parent_refcount (structure, NULL);
99     gst_structure_free (structure);
100   }
101
102   g_slice_free1 (sizeof (GstContext), context);
103 }
104
105 static void gst_context_init (GstContext * context);
106
107 static GstContext *
108 _gst_context_copy (GstContext * context)
109 {
110   GstContext *copy;
111   GstStructure *structure;
112
113   GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context,
114       GST_CONTEXT_STRUCTURE (context));
115
116   copy = g_slice_new0 (GstContext);
117
118   gst_context_init (copy);
119
120   structure = GST_CONTEXT_STRUCTURE (context);
121   GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
122   gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
123       &copy->mini_object.refcount);
124
125   return GST_CONTEXT_CAST (copy);
126 }
127
128 static void
129 gst_context_init (GstContext * context)
130 {
131   gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type,
132       (GstMiniObjectCopyFunction) _gst_context_copy, NULL,
133       (GstMiniObjectFreeFunction) _gst_context_free);
134 }
135
136 /**
137  * gst_context_new:
138  *
139  * Create a new context.
140  *
141  * Returns: (transfer full): The new context.
142  *
143  * Since: 1.2
144  */
145 GstContext *
146 gst_context_new (void)
147 {
148   GstContext *context;
149   GstStructure *structure;
150
151   context = g_slice_new0 (GstContext);
152
153   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
154
155   structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
156   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
157   gst_context_init (context);
158
159   GST_CONTEXT_STRUCTURE (context) = structure;
160
161   return context;
162 }
163
164 /**
165  * gst_context_get_structure:
166  * @context: The #GstContext.
167  *
168  * Access the structure of the context.
169  *
170  * Returns: (transfer none): The structure of the context. The structure is
171  * still owned by the context, which means that you should not modify it,
172  * free it and that the pointer becomes invalid when you free the context.
173  *
174  * Since: 1.2
175  */
176 const GstStructure *
177 gst_context_get_structure (GstContext * context)
178 {
179   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
180
181   return GST_CONTEXT_STRUCTURE (context);
182 }
183
184 /**
185  * gst_context_writable_structure:
186  * @context: The #GstContext.
187  *
188  * Get a writable version of the structure.
189  *
190  * Returns: The structure of the context. The structure is still
191  * owned by the event, which means that you should not free it and
192  * that the pointer becomes invalid when you free the event.
193  * This function checks if @context is writable.
194  *
195  * Since: 1.2
196  */
197 GstStructure *
198 gst_context_writable_structure (GstContext * context)
199 {
200   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
201   g_return_val_if_fail (gst_context_is_writable (context), NULL);
202
203   return GST_CONTEXT_STRUCTURE (context);
204 }