00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "xmms/xmms_object.h"
00018 #include "xmms/xmms_log.h"
00019 #include "xmmsc/xmmsc_idnumbers.h"
00020
00021 #include <stdarg.h>
00022 #include <string.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 typedef struct {
00035 xmms_object_handler_t handler;
00036 gpointer userdata;
00037 } xmms_object_handler_entry_t;
00038
00039
00040
00041
00042
00043 void
00044 xmms_object_cleanup (xmms_object_t *object)
00045 {
00046 gint i;
00047
00048 g_return_if_fail (object);
00049 g_return_if_fail (XMMS_IS_OBJECT (object));
00050
00051 for (i = 0; i < XMMS_IPC_SIGNAL_END; i++) {
00052 if (object->signals[i]) {
00053 GList *list = object->signals[i];
00054
00055 while (list) {
00056 g_free (list->data);
00057 list = g_list_delete_link (list, list);
00058 }
00059 }
00060 }
00061
00062 g_mutex_free (object->mutex);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 void
00080 xmms_object_connect (xmms_object_t *object, guint32 signalid,
00081 xmms_object_handler_t handler, gpointer userdata)
00082 {
00083 GList *list = NULL;
00084 GList *node;
00085 xmms_object_handler_entry_t *entry;
00086
00087 g_return_if_fail (object);
00088 g_return_if_fail (XMMS_IS_OBJECT (object));
00089 g_return_if_fail (handler);
00090
00091 entry = g_new0 (xmms_object_handler_entry_t, 1);
00092 entry->handler = handler;
00093 entry->userdata = userdata;
00094
00095 if (object->signals[signalid]) {
00096 node = object->signals[signalid];
00097 list = g_list_prepend (node, entry);
00098 object->signals[signalid] = list;
00099 } else {
00100 list = g_list_prepend (list, entry);
00101 object->signals[signalid] = list;
00102 }
00103
00104 }
00105
00106
00107
00108
00109
00110 void
00111 xmms_object_disconnect (xmms_object_t *object, guint32 signalid,
00112 xmms_object_handler_t handler, gpointer userdata)
00113 {
00114 GList *list = NULL, *node;
00115 xmms_object_handler_entry_t *entry;
00116
00117 g_return_if_fail (object);
00118 g_return_if_fail (XMMS_IS_OBJECT (object));
00119 g_return_if_fail (handler);
00120
00121 g_mutex_lock (object->mutex);
00122
00123 list = object->signals[signalid];
00124
00125 for (node = list; node; node = g_list_next (node)) {
00126 entry = node->data;
00127
00128 if (entry->handler == handler && entry->userdata == userdata)
00129 break;
00130 }
00131
00132 if (node)
00133 object->signals[signalid] = g_list_remove_link (list, node);
00134 g_mutex_unlock (object->mutex);
00135
00136 g_return_if_fail (node);
00137
00138 g_free (node->data);
00139 g_list_free_1 (node);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 void
00151 xmms_object_emit (xmms_object_t *object, guint32 signalid, gconstpointer data)
00152 {
00153 GList *list, *node, *list2 = NULL;
00154 xmms_object_handler_entry_t *entry;
00155
00156 g_return_if_fail (object);
00157 g_return_if_fail (XMMS_IS_OBJECT (object));
00158
00159 g_mutex_lock (object->mutex);
00160
00161 list = object->signals[signalid];
00162 for (node = list; node; node = g_list_next (node)) {
00163 entry = node->data;
00164
00165 list2 = g_list_prepend (list2, entry);
00166 }
00167
00168 g_mutex_unlock (object->mutex);
00169
00170 while (list2) {
00171 entry = list2->data;
00172
00173 if (entry && entry->handler)
00174 entry->handler (object, data, entry->userdata);
00175
00176 list2 = g_list_delete_link (list2, list2);
00177 }
00178 }
00179
00180 xmms_object_cmd_value_t *
00181 xmms_object_cmd_value_bin_new (GString *bin)
00182 {
00183 xmms_object_cmd_value_t *val;
00184 val = g_new0 (xmms_object_cmd_value_t, 1);
00185 val->value.bin = bin;
00186 val->type = XMMS_OBJECT_CMD_ARG_BIN;
00187 val->refcount = 1;
00188 return val;
00189
00190 }
00191
00192 xmms_object_cmd_value_t *
00193 xmms_object_cmd_value_str_new (const gchar *string)
00194 {
00195 xmms_object_cmd_value_t *val;
00196 val = g_new0 (xmms_object_cmd_value_t, 1);
00197 val->value.string = g_strdup (string);
00198 val->type = XMMS_OBJECT_CMD_ARG_STRING;
00199 val->refcount = 1;
00200 return val;
00201 }
00202
00203 xmms_object_cmd_value_t *
00204 xmms_object_cmd_value_uint_new (guint32 uint)
00205 {
00206 xmms_object_cmd_value_t *val;
00207 val = g_new0 (xmms_object_cmd_value_t, 1);
00208 val->value.uint32 = uint;
00209 val->type = XMMS_OBJECT_CMD_ARG_UINT32;
00210 val->refcount = 1;
00211 return val;
00212 }
00213
00214 xmms_object_cmd_value_t *
00215 xmms_object_cmd_value_int_new (gint32 i)
00216 {
00217 xmms_object_cmd_value_t *val;
00218 val = g_new0 (xmms_object_cmd_value_t, 1);
00219 val->value.int32 = i;
00220 val->type = XMMS_OBJECT_CMD_ARG_INT32;
00221 val->refcount = 1;
00222 return val;
00223 }
00224
00225 xmms_object_cmd_value_t *
00226 xmms_object_cmd_value_dict_new (GTree *dict)
00227 {
00228 xmms_object_cmd_value_t *val;
00229 val = g_new0 (xmms_object_cmd_value_t, 1);
00230 val->value.dict = dict;
00231 val->type = XMMS_OBJECT_CMD_ARG_DICT;
00232 val->refcount = 1;
00233 return val;
00234 }
00235
00236 xmms_object_cmd_value_t *
00237 xmms_object_cmd_value_hash_table_new (GHashTable *hash)
00238 {
00239 xmms_object_cmd_value_t *val;
00240 val = g_new0 (xmms_object_cmd_value_t, 1);
00241 val->value.hash = hash;
00242 val->type = XMMS_OBJECT_CMD_ARG_HASH_TABLE;
00243 val->refcount = 1;
00244 return val;
00245 }
00246
00247 xmms_object_cmd_value_t *
00248 xmms_object_cmd_value_propdict_new (GList *list)
00249 {
00250 xmms_object_cmd_value_t *val;
00251 val = g_new0 (xmms_object_cmd_value_t, 1);
00252 val->value.list = list;
00253 val->type = XMMS_OBJECT_CMD_ARG_PROPDICT;
00254 val->refcount = 1;
00255 return val;
00256 }
00257
00258 xmms_object_cmd_value_t *
00259 xmms_object_cmd_value_list_new (GList *list)
00260 {
00261 xmms_object_cmd_value_t *val;
00262 val = g_new0 (xmms_object_cmd_value_t, 1);
00263 val->value.list = list;
00264 val->type = XMMS_OBJECT_CMD_ARG_LIST;
00265 val->refcount = 1;
00266 return val;
00267 }
00268
00269 xmms_object_cmd_value_t *
00270 xmms_object_cmd_value_coll_new (xmmsc_coll_t *coll)
00271 {
00272 xmms_object_cmd_value_t *val;
00273 val = g_new0 (xmms_object_cmd_value_t, 1);
00274 val->value.coll = coll;
00275 val->type = XMMS_OBJECT_CMD_ARG_COLL;
00276 val->refcount = 1;
00277 return val;
00278 }
00279
00280 xmms_object_cmd_value_t *
00281 xmms_object_cmd_value_none_new (void)
00282 {
00283 xmms_object_cmd_value_t *val;
00284 val = g_new0 (xmms_object_cmd_value_t, 1);
00285 val->type = XMMS_OBJECT_CMD_ARG_NONE;
00286 val->refcount = 1;
00287 return val;
00288 }
00289
00290 static void
00291 xmms_object_cmd_value_free (xmms_object_cmd_value_t *v)
00292 {
00293 switch (v->type) {
00294 case XMMS_OBJECT_CMD_ARG_STRING:
00295 if (v->value.string)
00296 g_free (v->value.string);
00297 break;
00298 case XMMS_OBJECT_CMD_ARG_BIN:
00299 if (v->value.bin)
00300 g_string_free (v->value.bin, TRUE);
00301 break;
00302 case XMMS_OBJECT_CMD_ARG_LIST:
00303 case XMMS_OBJECT_CMD_ARG_PROPDICT:
00304 while (v->value.list) {
00305 xmms_object_cmd_value_unref (v->value.list->data);
00306 v->value.list = g_list_delete_link (v->value.list,
00307 v->value.list);
00308 }
00309 break;
00310 case XMMS_OBJECT_CMD_ARG_STRINGLIST:
00311 while (v->value.list) {
00312 g_free (v->value.list->data);
00313 v->value.list = g_list_delete_link (v->value.list,
00314 v->value.list);
00315 }
00316 break;
00317 case XMMS_OBJECT_CMD_ARG_DICT:
00318 if (v->value.dict) {
00319 g_tree_destroy (v->value.dict);
00320 }
00321
00322 break;
00323 case XMMS_OBJECT_CMD_ARG_HASH_TABLE:
00324 if (v->value.hash) {
00325 g_hash_table_destroy (v->value.hash);
00326 }
00327
00328 break;
00329
00330 case XMMS_OBJECT_CMD_ARG_COLL:
00331 if (v->value.coll) {
00332 xmmsc_coll_unref (v->value.coll);
00333 }
00334 break;
00335 default:
00336 break;
00337 }
00338
00339 g_free (v);
00340 }
00341
00342 void
00343 xmms_object_cmd_value_unref (xmms_object_cmd_value_t *val)
00344 {
00345 g_return_if_fail (val);
00346
00347 val->refcount--;
00348
00349 if (!val->refcount) {
00350 xmms_object_cmd_value_free (val);
00351 }
00352 }
00353
00354 xmms_object_cmd_value_t *
00355 xmms_object_cmd_value_ref (xmms_object_cmd_value_t *val)
00356 {
00357 g_return_val_if_fail (val, NULL);
00358
00359 val->refcount++;
00360
00361 return val;
00362 }
00363
00364
00365
00366
00367
00368 void
00369 xmms_object_cmd_arg_init (xmms_object_cmd_arg_t *arg)
00370 {
00371 g_return_if_fail (arg);
00372
00373 memset (arg, 0, sizeof (xmms_object_cmd_arg_t));
00374 xmms_error_reset (&arg->error);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 void
00389 xmms_object_emit_f (xmms_object_t *object, guint32 signalid,
00390 xmms_object_cmd_arg_type_t type, ...)
00391 {
00392 va_list ap;
00393 xmms_object_cmd_arg_t arg;
00394
00395 xmms_object_cmd_arg_init (&arg);
00396
00397 va_start (ap, type);
00398
00399 switch (type) {
00400 case XMMS_OBJECT_CMD_ARG_UINT32:
00401 arg.retval = xmms_object_cmd_value_uint_new (va_arg (ap, guint32));
00402 break;
00403 case XMMS_OBJECT_CMD_ARG_INT32:
00404 arg.retval = xmms_object_cmd_value_int_new (va_arg (ap, gint32));
00405 break;
00406 case XMMS_OBJECT_CMD_ARG_STRING:
00407 arg.retval = xmms_object_cmd_value_str_new (va_arg (ap, gchar *));
00408 break;
00409 case XMMS_OBJECT_CMD_ARG_BIN:
00410 arg.retval = xmms_object_cmd_value_bin_new (va_arg (ap, GString *));
00411 break;
00412 case XMMS_OBJECT_CMD_ARG_DICT:
00413 arg.retval = xmms_object_cmd_value_dict_new (va_arg (ap, GTree *));
00414 break;
00415 case XMMS_OBJECT_CMD_ARG_HASH_TABLE:
00416 arg.retval = xmms_object_cmd_value_hash_table_new (va_arg (ap, GHashTable *));
00417 break;
00418 case XMMS_OBJECT_CMD_ARG_LIST:
00419 case XMMS_OBJECT_CMD_ARG_PROPDICT:
00420 case XMMS_OBJECT_CMD_ARG_STRINGLIST:
00421 arg.retval = xmms_object_cmd_value_list_new (va_arg (ap, GList *));
00422 break;
00423 case XMMS_OBJECT_CMD_ARG_COLL:
00424 arg.retval = xmms_object_cmd_value_coll_new (va_arg (ap, xmmsc_coll_t *));
00425 break;
00426 case XMMS_OBJECT_CMD_ARG_NONE:
00427 arg.retval = xmms_object_cmd_value_none_new ();
00428 break;
00429 }
00430 va_end (ap);
00431
00432 xmms_object_emit (object, signalid, &arg);
00433
00434
00435
00436
00437
00438
00439
00440 switch (type) {
00441 case XMMS_OBJECT_CMD_ARG_STRING:
00442 case XMMS_OBJECT_CMD_ARG_NONE:
00443 xmms_object_cmd_value_unref (arg.retval);
00444 break;
00445 default:
00446 g_free (arg.retval);
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 void
00459 xmms_object_cmd_add (xmms_object_t *object, guint cmdid,
00460 xmms_object_cmd_desc_t *desc)
00461 {
00462 g_return_if_fail (object);
00463 g_return_if_fail (desc);
00464
00465 object->cmds[cmdid] = desc;
00466 }
00467
00468
00469
00470
00471
00472 void
00473 xmms_object_cmd_call (xmms_object_t *object, guint cmdid, xmms_object_cmd_arg_t *arg)
00474 {
00475 xmms_object_cmd_desc_t *desc;
00476
00477 g_return_if_fail (object);
00478
00479 desc = object->cmds[cmdid];
00480
00481 if (desc->func)
00482 desc->func (object, arg);
00483 }
00484
00485
00486
00487 void
00488 __int_xmms_object_unref (xmms_object_t *object)
00489 {
00490 g_return_if_fail (object->ref > 0);
00491 object->ref--;
00492 if (object->ref == 0) {
00493 xmms_object_emit (object, XMMS_IPC_SIGNAL_OBJECT_DESTROYED, NULL);
00494 if (object->destroy_func)
00495 object->destroy_func (object);
00496 xmms_object_cleanup (object);
00497 g_free (object);
00498 }
00499 }
00500
00501 xmms_object_t *
00502 __int_xmms_object_new (gint size, xmms_object_destroy_func_t destfunc)
00503 {
00504 xmms_object_t *ret;
00505
00506 ret = g_malloc0 (size);
00507 ret->destroy_func = destfunc;
00508 ret->id = XMMS_OBJECT_MID;
00509
00510 ret->mutex = g_mutex_new ();
00511 xmms_object_ref (ret);
00512
00513 return ret;
00514 }
00515