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 Intels 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 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 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 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 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 */ 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 115 static void mix_params_finalize (MixParams * obj) 116 { 117 /* do nothing */ 118 } 119 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 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 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 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 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 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 */ 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 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 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 */ 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