1 /*
2  INTEL CONFIDENTIAL
3  Copyright 2009 Intel Corporation All Rights Reserved.
4  The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5 
6  No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7 */
8 
9 /**
10  * SECTION:mixparams
11  * @short_description: Lightweight base class for the MIX media params
12  *
13  */
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include "mixparams.h"
19 #include <gobject/gvaluecollector.h>
20 
21 
22 #define DEBUG_REFCOUNT
23 
24 static void mix_params_class_init (gpointer g_class, gpointer class_data);
25 static void mix_params_init (GTypeInstance * instance, gpointer klass);
26 
27 static void mix_params_finalize(MixParams * obj);
28 static gboolean mix_params_copy_default (MixParams *target, const MixParams *src);
29 static MixParams *mix_params_dup_default(const MixParams *obj);
30 static gboolean mix_params_equal_default (MixParams *first, MixParams *second);
31 
mix_params_get_type(void)32 GType mix_params_get_type (void)
33 {
34   static GType _mix_params_type = 0;
35 
36   if (G_UNLIKELY (_mix_params_type == 0)) {
37 
38     GTypeInfo info = {
39       sizeof (MixParamsClass),
40       NULL,
41       NULL,
42       mix_params_class_init,
43       NULL,
44       NULL,
45       sizeof (MixParams),
46       0,
47       (GInstanceInitFunc) mix_params_init,
48       NULL
49     };
50 
51     static const GTypeFundamentalInfo fundamental_info = {
52       (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE |
53           G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE)
54     };
55 
56     info.value_table = NULL;
57 
58     _mix_params_type = g_type_fundamental_next ();
59     g_type_register_fundamental (_mix_params_type, "MixParams", &info, &fundamental_info, G_TYPE_FLAG_ABSTRACT);
60 
61   }
62 
63   return _mix_params_type;
64 }
65 
mix_params_class_init(gpointer g_class,gpointer class_data)66 static void mix_params_class_init (gpointer g_class, gpointer class_data)
67 {
68   MixParamsClass *klass = MIX_PARAMS_CLASS (g_class);
69 
70   klass->dup = mix_params_dup_default;
71   klass->copy = mix_params_copy_default;
72   klass->finalize = mix_params_finalize;
73   klass->equal = mix_params_equal_default;
74 }
75 
mix_params_init(GTypeInstance * instance,gpointer klass)76 static void mix_params_init (GTypeInstance * instance, gpointer klass)
77 {
78   MixParams *obj = MIX_PARAMS_CAST (instance);
79 
80   obj->refcount = 1;
81 }
82 
mix_params_copy(MixParams * target,const MixParams * src)83 gboolean mix_params_copy (MixParams *target, const MixParams *src)
84 {
85   /* Use the target object class. Because it knows what it is looking for. */
86   MixParamsClass *klass = MIX_PARAMS_GET_CLASS(target);
87   if (klass->copy)
88   {
89     return klass->copy(target, src);
90   }
91   else
92   {
93     return mix_params_copy_default(target, src);
94   }
95 }
96 
97 /**
98  * mix_params_copy_default:
99  * @target: target
100  * @src: source
101  *
102  * The default copy method of this object. Perhap copy at this level.
103  * Assign this to the copy vmethod.
104  */
mix_params_copy_default(MixParams * target,const MixParams * src)105 static gboolean mix_params_copy_default (MixParams *target, const MixParams *src)
106 {
107   if (MIX_IS_PARAMS(target) && MIX_IS_PARAMS(src))
108   {
109     // TODO perform deep copy.
110     return TRUE;
111   }
112   return FALSE;
113 }
114 
mix_params_finalize(MixParams * obj)115 static void mix_params_finalize (MixParams * obj)
116 {
117   /* do nothing */
118 }
119 
mix_params_dup(const MixParams * obj)120 MixParams *mix_params_dup(const MixParams *obj)
121 {
122   MixParamsClass *klass = MIX_PARAMS_GET_CLASS(obj);
123 
124   if (klass->dup)
125   {
126     return klass->dup(obj);
127   }
128   else if (MIX_IS_PARAMS(obj))
129   {
130     return mix_params_dup_default(obj);
131   }
132   return NULL;
133 }
134 
mix_params_dup_default(const MixParams * obj)135 static MixParams *mix_params_dup_default(const MixParams *obj)
136 {
137     MixParams *ret = mix_params_new();
138     if (mix_params_copy(ret, obj))
139     {
140       return ret;
141     }
142 
143     return NULL;
144 }
145 
mix_params_new(GType type)146 MixParams* mix_params_new (GType type)
147 {
148   MixParams *obj;
149 
150   /* we don't support dynamic types because they really aren't useful,
151    * and could cause refcount problems */
152   obj = (MixParams *) g_type_create_instance (type);
153 
154   return obj;
155 }
156 
mix_params_ref(MixParams * obj)157 MixParams* mix_params_ref (MixParams *obj)
158 {
159   g_return_val_if_fail(MIX_IS_PARAMS (obj), NULL);
160 
161   g_atomic_int_inc(&obj->refcount);
162 
163   return obj;
164 }
165 
mix_params_free(MixParams * obj)166 static void mix_params_free(MixParams *obj)
167 {
168   MixParamsClass *klass = NULL;
169 
170   klass = MIX_PARAMS_GET_CLASS(obj);
171   klass->finalize(obj);
172 
173   /* Should we support recycling the object? */
174   /* If so, refcount handling is slightly different. */
175   /* i.e. If the refcount is still 0 we can really free the object, else the finalize method recycled the object -- but to where? */
176 
177   if (g_atomic_int_get (&obj->refcount) == 0) {
178 
179     g_type_free_instance ((GTypeInstance *) obj);
180   }
181 }
182 
mix_params_unref(MixParams * obj)183 void mix_params_unref (MixParams *obj)
184 {
185   g_return_if_fail (obj != NULL);
186   g_return_if_fail (obj->refcount > 0);
187 
188   if (G_UNLIKELY (g_atomic_int_dec_and_test (&obj->refcount))) {
189     mix_params_free (obj);
190   }
191 }
192 
193 /**
194  * mix_params_replace:
195  * @olddata: pointer to a pointer to a object to be replaced
196  * @newdata: pointer to new object
197  *
198  * Modifies a pointer to point to a new object.  The modification
199  * is done atomically, and the reference counts are updated correctly.
200  * Either @newdata and the value pointed to by @olddata may be NULL.
201  */
mix_params_replace(MixParams ** olddata,MixParams * newdata)202 void mix_params_replace (MixParams **olddata, MixParams *newdata)
203 {
204   MixParams *olddata_val;
205 
206   g_return_if_fail (olddata != NULL);
207 
208   olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
209 
210   if (olddata_val == newdata)
211     return;
212 
213   if (newdata)
214     mix_params_ref (newdata);
215 
216   while (!g_atomic_pointer_compare_and_exchange ((gpointer *) olddata, olddata_val, newdata))
217   {
218     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
219   }
220 
221   if (olddata_val)
222     mix_params_unref (olddata_val);
223 
224 }
225 
mix_params_equal(MixParams * first,MixParams * second)226 gboolean mix_params_equal (MixParams *first, MixParams *second)
227 {
228   if (MIX_IS_PARAMS(first))
229   {
230     MixParamsClass *klass = MIX_PARAMS_GET_CLASS(first);
231 
232     if (klass->equal)
233     {
234       return klass->equal(first, second);
235     }
236     else
237     {
238       return mix_params_equal_default(first, second);
239     }
240   }
241   else
242     return FALSE;
243 }
244 
mix_params_equal_default(MixParams * first,MixParams * second)245 static gboolean mix_params_equal_default (MixParams *first, MixParams *second)
246 {
247   if (MIX_IS_PARAMS(first) && MIX_IS_PARAMS(second))
248   {
249     gboolean ret = TRUE;
250 
251     // Do data comparison here.
252 
253     return ret;
254   }
255   else
256     return FALSE;
257 }
258 
259 /**
260  * mix_value_dup_params:
261  * @value:   a valid #GValue of %MIX_TYPE_PARAMS derived type
262  * @returns: object contents of @value
263  *
264  * Get the contents of a #MIX_TYPE_PARAMS derived #GValue,
265  * increasing its reference count.
266  */
mix_value_dup_params(const GValue * value)267 MixParams* mix_value_dup_params (const GValue * value)
268 {
269   g_return_val_if_fail (MIX_VALUE_HOLDS_PARAMS (value), NULL);
270 
271   return mix_params_ref (value->data[0].v_pointer);
272 }
273 
274 
275