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