00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <glib.h>
00018 #include <string.h>
00019
00020 #include "xmms/xmms_log.h"
00021 #include "xmms/xmms_config.h"
00022 #include "xmmspriv/xmms_ipc.h"
00023 #include "xmmsc/xmmsc_ipc_msg.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 typedef struct xmms_ipc_object_pool_t {
00039 xmms_object_t *objects[XMMS_IPC_OBJECT_END];
00040 xmms_object_t *signals[XMMS_IPC_SIGNAL_END];
00041 xmms_object_t *broadcasts[XMMS_IPC_SIGNAL_END];
00042 } xmms_ipc_object_pool_t;
00043
00044
00045
00046
00047
00048 struct xmms_ipc_St {
00049 xmms_ipc_transport_t *transport;
00050 GList *clients;
00051 GIOChannel *chan;
00052 GMutex *mutex_lock;
00053 xmms_object_t **objects;
00054 xmms_object_t **signals;
00055 xmms_object_t **broadcasts;
00056 };
00057
00058
00059
00060
00061
00062 typedef struct xmms_ipc_client_St {
00063 GMainLoop *ml;
00064 GIOChannel *iochan;
00065
00066 xmms_ipc_transport_t *transport;
00067 xmms_ipc_msg_t *read_msg;
00068 xmms_ipc_t *ipc;
00069
00070
00071
00072
00073 GMutex *lock;
00074
00075
00076 GQueue *out_msg;
00077
00078 guint pendingsignals[XMMS_IPC_SIGNAL_END];
00079 GList *broadcasts[XMMS_IPC_SIGNAL_END];
00080 } xmms_ipc_client_t;
00081
00082 static GMutex *ipc_servers_lock;
00083 static GList *ipc_servers = NULL;
00084
00085 static GMutex *ipc_object_pool_lock;
00086 static struct xmms_ipc_object_pool_t *ipc_object_pool = NULL;
00087
00088 static void xmms_ipc_client_destroy (xmms_ipc_client_t *client);
00089
00090 static void xmms_ipc_register_signal (xmms_ipc_client_t *client, xmms_ipc_msg_t *msg, xmmsv_t *arguments);
00091 static void xmms_ipc_register_broadcast (xmms_ipc_client_t *client, xmms_ipc_msg_t *msg, xmmsv_t *arguments);
00092 static gboolean xmms_ipc_client_msg_write (xmms_ipc_client_t *client, xmms_ipc_msg_t *msg);
00093
00094 static gboolean
00095 type_and_msg_to_arg (xmmsv_type_t expected_type, xmmsv_t *argument_list,
00096 xmms_object_cmd_arg_t *arg, gint i)
00097 {
00098 xmmsv_t *arg_value;
00099 xmmsv_type_t actual_type;
00100
00101 if (argument_list && xmmsv_list_get (argument_list, i, &arg_value)) {
00102 xmmsv_ref (arg_value);
00103 } else {
00104 arg_value = xmmsv_new_none ();
00105 }
00106
00107 actual_type = xmmsv_get_type (arg_value);
00108
00109 if (actual_type != expected_type) {
00110 XMMS_DBG ("Expected type %i, but got type %i",
00111 expected_type, actual_type);
00112
00113 xmmsv_unref (arg_value);
00114
00115 return FALSE;
00116 } else {
00117 arg->values[i] = arg_value;
00118
00119 return TRUE;
00120 }
00121 }
00122
00123 static void
00124 xmms_ipc_handle_cmd_value (xmms_ipc_msg_t *msg, xmmsv_t *val)
00125 {
00126 if (xmms_ipc_msg_put_value (msg, val) == (uint32_t) -1) {
00127 xmms_log_error ("Failed to serialize the return value into the IPC message!");
00128 }
00129 }
00130
00131 static void
00132 xmms_ipc_register_signal (xmms_ipc_client_t *client,
00133 xmms_ipc_msg_t *msg, xmmsv_t *arguments)
00134 {
00135 xmmsv_t *arg;
00136 gint32 signalid;
00137 int r;
00138
00139 if (!arguments || !xmmsv_list_get (arguments, 0, &arg)) {
00140 xmms_log_error ("No signalid in this msg?!");
00141 return;
00142 }
00143
00144 r = xmmsv_get_int (arg, &signalid);
00145
00146 if (!r) {
00147 xmms_log_error ("Cannot extract signal id from value");
00148 return;
00149 }
00150
00151 if (signalid < 0 || signalid >= XMMS_IPC_SIGNAL_END) {
00152 xmms_log_error ("Bad signal id (%d)", signalid);
00153 return;
00154 }
00155
00156 g_mutex_lock (client->lock);
00157 client->pendingsignals[signalid] = xmms_ipc_msg_get_cookie (msg);
00158 g_mutex_unlock (client->lock);
00159 }
00160
00161 static void
00162 xmms_ipc_register_broadcast (xmms_ipc_client_t *client,
00163 xmms_ipc_msg_t *msg, xmmsv_t *arguments)
00164 {
00165 xmmsv_t *arg;
00166 gint32 broadcastid;
00167 int r;
00168
00169 if (!arguments || !xmmsv_list_get (arguments, 0, &arg)) {
00170 xmms_log_error ("No broadcastid in this msg?!");
00171 return;
00172 }
00173
00174 r = xmmsv_get_int (arg, &broadcastid);
00175
00176 if (!r) {
00177 xmms_log_error ("Cannot extract broadcast id from value");
00178 return;
00179 }
00180
00181 if (broadcastid < 0 || broadcastid >= XMMS_IPC_SIGNAL_END) {
00182 xmms_log_error ("Bad broadcast id (%d)", broadcastid);
00183 return;
00184 }
00185
00186 g_mutex_lock (client->lock);
00187 client->broadcasts[broadcastid] =
00188 g_list_append (client->broadcasts[broadcastid],
00189 GUINT_TO_POINTER (xmms_ipc_msg_get_cookie (msg)));
00190
00191 g_mutex_unlock (client->lock);
00192 }
00193
00194 static void
00195 process_msg (xmms_ipc_client_t *client, xmms_ipc_msg_t *msg)
00196 {
00197 xmms_object_t *object;
00198 xmms_object_cmd_desc_t *cmd = NULL;
00199 xmms_object_cmd_arg_t arg;
00200 xmms_ipc_msg_t *retmsg;
00201 xmmsv_t *error, *arguments;
00202 uint32_t objid, cmdid;
00203 gint i;
00204
00205 g_return_if_fail (msg);
00206
00207 objid = xmms_ipc_msg_get_object (msg);
00208 cmdid = xmms_ipc_msg_get_cmd (msg);
00209
00210 if (!xmms_ipc_msg_get_value (msg, &arguments)) {
00211 xmms_log_error ("Cannot read command arguments. "
00212 "Ignoring command.");
00213
00214 return;
00215 }
00216
00217 if (objid == XMMS_IPC_OBJECT_SIGNAL) {
00218 if (cmdid == XMMS_IPC_CMD_SIGNAL) {
00219 xmms_ipc_register_signal (client, msg, arguments);
00220 } else if (cmdid == XMMS_IPC_CMD_BROADCAST) {
00221 xmms_ipc_register_broadcast (client, msg, arguments);
00222 } else {
00223 xmms_log_error ("Bad command id (%d) for signal object", cmdid);
00224 }
00225
00226 goto out;
00227 }
00228
00229 if (objid >= XMMS_IPC_OBJECT_END) {
00230 xmms_log_error ("Bad object id (%d)", objid);
00231 goto out;
00232 }
00233
00234 g_mutex_lock (ipc_object_pool_lock);
00235 object = ipc_object_pool->objects[objid];
00236 g_mutex_unlock (ipc_object_pool_lock);
00237 if (!object) {
00238 xmms_log_error ("Object %d was not found!", objid);
00239 goto out;
00240 }
00241
00242 if (object->cmds)
00243 cmd = g_tree_lookup (object->cmds, GUINT_TO_POINTER (cmdid));
00244
00245 if (!cmd) {
00246 xmms_log_error ("No such cmd %d on object %d", cmdid, objid);
00247 goto out;
00248 }
00249
00250 xmms_object_cmd_arg_init (&arg);
00251
00252 for (i = 0; i < XMMS_OBJECT_CMD_MAX_ARGS; i++) {
00253 if (!type_and_msg_to_arg (cmd->args[i], arguments, &arg, i)) {
00254 xmms_log_error ("Error parsing args");
00255
00256 if (objid == XMMS_IPC_OBJECT_MAIN &&
00257 cmdid == XMMS_IPC_CMD_HELLO) {
00258 xmms_log_error ("Couldn't parse hello message. "
00259 "Maybe the client or libxmmsclient "
00260 "needs to be updated.");
00261 }
00262
00263 retmsg = xmms_ipc_msg_new (objid, XMMS_IPC_CMD_ERROR);
00264
00265 error = xmmsv_new_error ("Corrupt msg");
00266 xmms_ipc_msg_put_value (retmsg, error);
00267 xmmsv_unref (error);
00268
00269 goto err;
00270 }
00271
00272 }
00273
00274 xmms_object_cmd_call (object, cmdid, &arg);
00275 if (xmms_error_isok (&arg.error)) {
00276 retmsg = xmms_ipc_msg_new (objid, XMMS_IPC_CMD_REPLY);
00277 xmms_ipc_handle_cmd_value (retmsg, arg.retval);
00278 } else {
00279
00280
00281
00282
00283 retmsg = xmms_ipc_msg_new (objid, XMMS_IPC_CMD_ERROR);
00284
00285 error = xmmsv_new_error (xmms_error_message_get (&arg.error));
00286 xmms_ipc_msg_put_value (retmsg, error);
00287 xmmsv_unref (error);
00288
00289
00290
00291
00292
00293 }
00294
00295 if (arg.retval)
00296 xmmsv_unref (arg.retval);
00297
00298 err:
00299 for (i = 0; i < XMMS_OBJECT_CMD_MAX_ARGS; i++) {
00300 if (arg.values[i])
00301 xmmsv_unref (arg.values[i]);
00302 }
00303 xmms_ipc_msg_set_cookie (retmsg, xmms_ipc_msg_get_cookie (msg));
00304 g_mutex_lock (client->lock);
00305 xmms_ipc_client_msg_write (client, retmsg);
00306 g_mutex_unlock (client->lock);
00307
00308 out:
00309 if (arguments) {
00310 xmmsv_unref (arguments);
00311 }
00312 }
00313
00314
00315 static gboolean
00316 xmms_ipc_client_read_cb (GIOChannel *iochan,
00317 GIOCondition cond,
00318 gpointer data)
00319 {
00320 xmms_ipc_client_t *client = data;
00321 bool disconnect = FALSE;
00322
00323 g_return_val_if_fail (client, FALSE);
00324
00325 if (cond & G_IO_IN) {
00326 while (TRUE) {
00327 if (!client->read_msg) {
00328 client->read_msg = xmms_ipc_msg_alloc ();
00329 }
00330
00331 if (xmms_ipc_msg_read_transport (client->read_msg, client->transport, &disconnect)) {
00332 xmms_ipc_msg_t *msg = client->read_msg;
00333 client->read_msg = NULL;
00334 process_msg (client, msg);
00335 xmms_ipc_msg_destroy (msg);
00336 } else {
00337 break;
00338 }
00339 }
00340 }
00341
00342 if (disconnect || (cond & G_IO_HUP)) {
00343 if (client->read_msg) {
00344 xmms_ipc_msg_destroy (client->read_msg);
00345 client->read_msg = NULL;
00346 }
00347 XMMS_DBG ("disconnect was true!");
00348 g_main_loop_quit (client->ml);
00349 return FALSE;
00350 }
00351
00352 if (cond & G_IO_ERR) {
00353 xmms_log_error ("Client got error, maybe connection died?");
00354 g_main_loop_quit (client->ml);
00355 return FALSE;
00356 }
00357
00358 return TRUE;
00359 }
00360
00361 static gboolean
00362 xmms_ipc_client_write_cb (GIOChannel *iochan,
00363 GIOCondition cond,
00364 gpointer data)
00365 {
00366 xmms_ipc_client_t *client = data;
00367 bool disconnect = FALSE;
00368
00369 g_return_val_if_fail (client, FALSE);
00370
00371 while (TRUE) {
00372 xmms_ipc_msg_t *msg;
00373
00374 g_mutex_lock (client->lock);
00375 msg = g_queue_peek_head (client->out_msg);
00376 g_mutex_unlock (client->lock);
00377
00378 if (!msg)
00379 break;
00380
00381 if (!xmms_ipc_msg_write_transport (msg,
00382 client->transport,
00383 &disconnect)) {
00384 if (disconnect) {
00385 break;
00386 } else {
00387
00388 return TRUE;
00389 }
00390 }
00391
00392 g_mutex_lock (client->lock);
00393 g_queue_pop_head (client->out_msg);
00394 g_mutex_unlock (client->lock);
00395
00396 xmms_ipc_msg_destroy (msg);
00397 }
00398
00399 return FALSE;
00400 }
00401
00402 static gpointer
00403 xmms_ipc_client_thread (gpointer data)
00404 {
00405 xmms_ipc_client_t *client = data;
00406 GSource *source;
00407
00408 source = g_io_create_watch (client->iochan, G_IO_IN | G_IO_ERR | G_IO_HUP);
00409 g_source_set_callback (source,
00410 (GSourceFunc) xmms_ipc_client_read_cb,
00411 (gpointer) client,
00412 NULL);
00413 g_source_attach (source, g_main_loop_get_context (client->ml));
00414 g_source_unref (source);
00415
00416 g_main_loop_run (client->ml);
00417
00418 xmms_ipc_client_destroy (client);
00419
00420 return NULL;
00421 }
00422
00423 static xmms_ipc_client_t *
00424 xmms_ipc_client_new (xmms_ipc_t *ipc, xmms_ipc_transport_t *transport)
00425 {
00426 xmms_ipc_client_t *client;
00427 GMainContext *context;
00428 int fd;
00429
00430 g_return_val_if_fail (transport, NULL);
00431
00432 client = g_new0 (xmms_ipc_client_t, 1);
00433
00434 context = g_main_context_new ();
00435 client->ml = g_main_loop_new (context, FALSE);
00436 g_main_context_unref (context);
00437
00438 fd = xmms_ipc_transport_fd_get (transport);
00439 client->iochan = g_io_channel_unix_new (fd);
00440 g_return_val_if_fail (client->iochan, NULL);
00441
00442
00443
00444
00445 g_io_channel_set_encoding (client->iochan, NULL, NULL);
00446 g_io_channel_set_buffered (client->iochan, FALSE);
00447
00448 client->transport = transport;
00449 client->ipc = ipc;
00450 client->out_msg = g_queue_new ();
00451 client->lock = g_mutex_new ();
00452
00453 return client;
00454 }
00455
00456 static void
00457 xmms_ipc_client_destroy (xmms_ipc_client_t *client)
00458 {
00459 guint i;
00460
00461 XMMS_DBG ("Destroying client!");
00462
00463 if (client->ipc) {
00464 g_mutex_lock (client->ipc->mutex_lock);
00465 client->ipc->clients = g_list_remove (client->ipc->clients, client);
00466 g_mutex_unlock (client->ipc->mutex_lock);
00467 }
00468
00469 g_main_loop_unref (client->ml);
00470 g_io_channel_unref (client->iochan);
00471
00472 xmms_ipc_transport_destroy (client->transport);
00473
00474 g_mutex_lock (client->lock);
00475 while (!g_queue_is_empty (client->out_msg)) {
00476 xmms_ipc_msg_t *msg = g_queue_pop_head (client->out_msg);
00477 xmms_ipc_msg_destroy (msg);
00478 }
00479
00480 g_queue_free (client->out_msg);
00481
00482 for (i = 0; i < XMMS_IPC_SIGNAL_END; i++) {
00483 g_list_free (client->broadcasts[i]);
00484 }
00485
00486 g_mutex_unlock (client->lock);
00487 g_mutex_free (client->lock);
00488 g_free (client);
00489 }
00490
00491
00492
00493
00494 void
00495 on_config_ipcsocket_change (xmms_object_t *object, xmmsv_t *_data, gpointer udata)
00496 {
00497 const gchar *value;
00498
00499 XMMS_DBG ("Shutting down ipc server threads through config property \"core.ipcsocket\" change.");
00500
00501 xmms_ipc_shutdown ();
00502 value = xmms_config_property_get_string ((xmms_config_property_t *) object);
00503 xmms_ipc_setup_server (value);
00504 }
00505
00506
00507
00508
00509
00510 static gboolean
00511 xmms_ipc_client_msg_write (xmms_ipc_client_t *client, xmms_ipc_msg_t *msg)
00512 {
00513 gboolean queue_empty;
00514
00515 g_return_val_if_fail (client, FALSE);
00516 g_return_val_if_fail (msg, FALSE);
00517
00518 queue_empty = g_queue_is_empty (client->out_msg);
00519 g_queue_push_tail (client->out_msg, msg);
00520
00521
00522 if (queue_empty) {
00523 GMainContext *context = g_main_loop_get_context (client->ml);
00524 GSource *source = g_io_create_watch (client->iochan, G_IO_OUT);
00525
00526 g_source_set_callback (source,
00527 (GSourceFunc) xmms_ipc_client_write_cb,
00528 (gpointer) client,
00529 NULL);
00530 g_source_attach (source, context);
00531 g_source_unref (source);
00532
00533 g_main_context_wakeup (context);
00534 }
00535
00536 return TRUE;
00537 }
00538
00539 static gboolean
00540 xmms_ipc_source_accept (GIOChannel *chan, GIOCondition cond, gpointer data)
00541 {
00542 xmms_ipc_t *ipc = (xmms_ipc_t *) data;
00543 xmms_ipc_transport_t *transport;
00544 xmms_ipc_client_t *client;
00545
00546 if (!(cond & G_IO_IN)) {
00547 xmms_log_error ("IPC listener got error/hup");
00548 return FALSE;
00549 }
00550
00551 XMMS_DBG ("Client connected");
00552 transport = xmms_ipc_server_accept (ipc->transport);
00553 if (!transport) {
00554 xmms_log_error ("accept returned null!");
00555 return TRUE;
00556 }
00557
00558 client = xmms_ipc_client_new (ipc, transport);
00559 if (!client) {
00560 xmms_ipc_transport_destroy (transport);
00561 return TRUE;
00562 }
00563
00564 g_mutex_lock (ipc->mutex_lock);
00565 ipc->clients = g_list_append (ipc->clients, client);
00566 g_mutex_unlock (ipc->mutex_lock);
00567
00568
00569
00570
00571 g_thread_create (xmms_ipc_client_thread, client, FALSE, NULL);
00572
00573 return TRUE;
00574 }
00575
00576
00577
00578
00579 static gboolean
00580 xmms_ipc_setup_server_internaly (xmms_ipc_t *ipc)
00581 {
00582 g_mutex_lock (ipc->mutex_lock);
00583 ipc->chan = g_io_channel_unix_new (xmms_ipc_transport_fd_get (ipc->transport));
00584
00585 g_io_channel_set_close_on_unref (ipc->chan, TRUE);
00586 g_io_channel_set_encoding (ipc->chan, NULL, NULL);
00587 g_io_channel_set_buffered (ipc->chan, FALSE);
00588
00589 g_io_add_watch (ipc->chan, G_IO_IN | G_IO_HUP | G_IO_ERR,
00590 xmms_ipc_source_accept, ipc);
00591 g_mutex_unlock (ipc->mutex_lock);
00592 return TRUE;
00593 }
00594
00595
00596
00597
00598 gboolean
00599 xmms_ipc_has_pending (guint signalid)
00600 {
00601 GList *c, *s;
00602 xmms_ipc_t *ipc;
00603
00604 g_mutex_lock (ipc_servers_lock);
00605
00606 for (s = ipc_servers; s; s = g_list_next (s)) {
00607 ipc = s->data;
00608 g_mutex_lock (ipc->mutex_lock);
00609 for (c = ipc->clients; c; c = g_list_next (c)) {
00610 xmms_ipc_client_t *cli = c->data;
00611 g_mutex_lock (cli->lock);
00612 if (cli->pendingsignals[signalid]) {
00613 g_mutex_unlock (cli->lock);
00614 g_mutex_unlock (ipc->mutex_lock);
00615 g_mutex_unlock (ipc_servers_lock);
00616 return TRUE;
00617 }
00618 g_mutex_unlock (cli->lock);
00619 }
00620 g_mutex_unlock (ipc->mutex_lock);
00621 }
00622
00623 g_mutex_unlock (ipc_servers_lock);
00624 return FALSE;
00625 }
00626
00627 static void
00628 xmms_ipc_signal_cb (xmms_object_t *object, xmmsv_t *arg, gpointer userdata)
00629 {
00630 GList *c, *s;
00631 guint signalid = GPOINTER_TO_UINT (userdata);
00632 xmms_ipc_t *ipc;
00633 xmms_ipc_msg_t *msg;
00634
00635 g_mutex_lock (ipc_servers_lock);
00636
00637 for (s = ipc_servers; s && s->data; s = g_list_next (s)) {
00638 ipc = s->data;
00639 g_mutex_lock (ipc->mutex_lock);
00640 for (c = ipc->clients; c; c = g_list_next (c)) {
00641 xmms_ipc_client_t *cli = c->data;
00642 g_mutex_lock (cli->lock);
00643 if (cli->pendingsignals[signalid]) {
00644 msg = xmms_ipc_msg_new (XMMS_IPC_OBJECT_SIGNAL, XMMS_IPC_CMD_SIGNAL);
00645 xmms_ipc_msg_set_cookie (msg, cli->pendingsignals[signalid]);
00646 xmms_ipc_handle_cmd_value (msg, arg);
00647 xmms_ipc_client_msg_write (cli, msg);
00648 cli->pendingsignals[signalid] = 0;
00649 }
00650 g_mutex_unlock (cli->lock);
00651 }
00652 g_mutex_unlock (ipc->mutex_lock);
00653 }
00654
00655 g_mutex_unlock (ipc_servers_lock);
00656
00657 }
00658
00659 static void
00660 xmms_ipc_broadcast_cb (xmms_object_t *object, xmmsv_t *arg, gpointer userdata)
00661 {
00662 GList *c, *s;
00663 guint broadcastid = GPOINTER_TO_UINT (userdata);
00664 xmms_ipc_t *ipc;
00665 xmms_ipc_msg_t *msg = NULL;
00666 GList *l;
00667
00668 g_mutex_lock (ipc_servers_lock);
00669
00670 for (s = ipc_servers; s && s->data; s = g_list_next (s)) {
00671 ipc = s->data;
00672 g_mutex_lock (ipc->mutex_lock);
00673 for (c = ipc->clients; c; c = g_list_next (c)) {
00674 xmms_ipc_client_t *cli = c->data;
00675
00676 g_mutex_lock (cli->lock);
00677 for (l = cli->broadcasts[broadcastid]; l; l = g_list_next (l)) {
00678 msg = xmms_ipc_msg_new (XMMS_IPC_OBJECT_SIGNAL, XMMS_IPC_CMD_BROADCAST);
00679 xmms_ipc_msg_set_cookie (msg, GPOINTER_TO_UINT (l->data));
00680 xmms_ipc_handle_cmd_value (msg, arg);
00681 xmms_ipc_client_msg_write (cli, msg);
00682 }
00683 g_mutex_unlock (cli->lock);
00684 }
00685 g_mutex_unlock (ipc->mutex_lock);
00686 }
00687 g_mutex_unlock (ipc_servers_lock);
00688 }
00689
00690
00691
00692
00693 void
00694 xmms_ipc_broadcast_register (xmms_object_t *object, xmms_ipc_signals_t signalid)
00695 {
00696 g_return_if_fail (object);
00697 g_mutex_lock (ipc_object_pool_lock);
00698
00699 ipc_object_pool->broadcasts[signalid] = object;
00700 xmms_object_connect (object, signalid, xmms_ipc_broadcast_cb, GUINT_TO_POINTER (signalid));
00701
00702 g_mutex_unlock (ipc_object_pool_lock);
00703 }
00704
00705
00706
00707
00708 void
00709 xmms_ipc_broadcast_unregister (xmms_ipc_signals_t signalid)
00710 {
00711 xmms_object_t *obj;
00712
00713 g_mutex_lock (ipc_object_pool_lock);
00714 obj = ipc_object_pool->broadcasts[signalid];
00715 if (obj) {
00716 xmms_object_disconnect (obj, signalid, xmms_ipc_broadcast_cb, GUINT_TO_POINTER (signalid));
00717 ipc_object_pool->broadcasts[signalid] = NULL;
00718 }
00719 g_mutex_unlock (ipc_object_pool_lock);
00720 }
00721
00722
00723
00724
00725 void
00726 xmms_ipc_signal_register (xmms_object_t *object, xmms_ipc_signals_t signalid)
00727 {
00728 g_return_if_fail (object);
00729
00730 g_mutex_lock (ipc_object_pool_lock);
00731 ipc_object_pool->signals[signalid] = object;
00732 xmms_object_connect (object, signalid, xmms_ipc_signal_cb, GUINT_TO_POINTER (signalid));
00733 g_mutex_unlock (ipc_object_pool_lock);
00734 }
00735
00736
00737
00738
00739 void
00740 xmms_ipc_signal_unregister (xmms_ipc_signals_t signalid)
00741 {
00742 xmms_object_t *obj;
00743
00744 g_mutex_lock (ipc_object_pool_lock);
00745 obj = ipc_object_pool->signals[signalid];
00746 if (obj) {
00747 xmms_object_disconnect (obj, signalid, xmms_ipc_signal_cb, GUINT_TO_POINTER (signalid));
00748 ipc_object_pool->signals[signalid] = NULL;
00749 }
00750 g_mutex_unlock (ipc_object_pool_lock);
00751 }
00752
00753
00754
00755
00756
00757 void
00758 xmms_ipc_object_register (xmms_ipc_objects_t objectid, xmms_object_t *object)
00759 {
00760 g_mutex_lock (ipc_object_pool_lock);
00761 ipc_object_pool->objects[objectid] = object;
00762 g_mutex_unlock (ipc_object_pool_lock);
00763 }
00764
00765
00766
00767
00768 void
00769 xmms_ipc_object_unregister (xmms_ipc_objects_t objectid)
00770 {
00771 g_mutex_lock (ipc_object_pool_lock);
00772 ipc_object_pool->objects[objectid] = NULL;
00773 g_mutex_unlock (ipc_object_pool_lock);
00774 }
00775
00776
00777
00778
00779 xmms_ipc_t *
00780 xmms_ipc_init (void)
00781 {
00782 ipc_servers_lock = g_mutex_new ();
00783 ipc_object_pool_lock = g_mutex_new ();
00784 ipc_object_pool = g_new0 (xmms_ipc_object_pool_t, 1);
00785 return NULL;
00786 }
00787
00788
00789
00790
00791 static void
00792 xmms_ipc_shutdown_server (xmms_ipc_t *ipc)
00793 {
00794 GList *c;
00795 xmms_ipc_client_t *co;
00796 if (!ipc) return;
00797
00798 g_mutex_lock (ipc->mutex_lock);
00799 g_source_remove_by_user_data (ipc);
00800 g_io_channel_unref (ipc->chan);
00801 xmms_ipc_transport_destroy (ipc->transport);
00802
00803 for (c = ipc->clients; c; c = g_list_next (c)) {
00804 co = c->data;
00805 if (!co) continue;
00806 co->ipc = NULL;
00807 }
00808
00809 g_list_free (ipc->clients);
00810 g_mutex_unlock (ipc->mutex_lock);
00811 g_mutex_free (ipc->mutex_lock);
00812
00813 g_free (ipc);
00814
00815 }
00816
00817
00818
00819
00820
00821 void
00822 xmms_ipc_shutdown (void)
00823 {
00824 GList *s = ipc_servers;
00825 xmms_ipc_t *ipc;
00826
00827 g_mutex_lock (ipc_servers_lock);
00828 while (s) {
00829 ipc = s->data;
00830 s = g_list_next (s);
00831 ipc_servers = g_list_remove (ipc_servers, ipc);
00832 xmms_ipc_shutdown_server (ipc);
00833 }
00834 g_mutex_unlock (ipc_servers_lock);
00835
00836 }
00837
00838
00839
00840
00841 gboolean
00842 xmms_ipc_setup_server (const gchar *path)
00843 {
00844 xmms_ipc_transport_t *transport;
00845 xmms_ipc_t *ipc;
00846 gchar **split;
00847 gint i = 0, num_init = 0;
00848 g_return_val_if_fail (path, FALSE);
00849
00850 split = g_strsplit (path, ";", 0);
00851
00852 for (i = 0; split && split[i]; i++) {
00853 ipc = g_new0 (xmms_ipc_t, 1);
00854 if (!ipc) {
00855 XMMS_DBG ("No IPC server initialized.");
00856 continue;
00857 }
00858
00859 transport = xmms_ipc_server_init (split[i]);
00860 if (!transport) {
00861 g_free (ipc);
00862 xmms_log_error ("Couldn't setup IPC listening on '%s'.", split[i]);
00863 continue;
00864 }
00865
00866
00867 ipc->mutex_lock = g_mutex_new ();
00868 ipc->transport = transport;
00869 ipc->signals = ipc_object_pool->signals;
00870 ipc->broadcasts = ipc_object_pool->broadcasts;
00871 ipc->objects = ipc_object_pool->objects;
00872
00873 xmms_ipc_setup_server_internaly (ipc);
00874 xmms_log_info ("IPC listening on '%s'.", split[i]);
00875
00876 g_mutex_lock (ipc_servers_lock);
00877 ipc_servers = g_list_prepend (ipc_servers, ipc);
00878 g_mutex_unlock (ipc_servers_lock);
00879
00880 num_init++;
00881 }
00882
00883 g_strfreev (split);
00884
00885
00886
00887 if (num_init < 1)
00888 return FALSE;
00889
00890 XMMS_DBG ("IPC setup done.");
00891 return TRUE;
00892 }
00893
00894
00895