63 typedef struct xmms_ipc_client_St {
83 static GMutex *ipc_servers_lock;
84 static GList *ipc_servers = NULL;
86 static GMutex *ipc_object_pool_lock;
99 xmms_log_error (
"Failed to serialize the return value into the IPC message!");
128 g_mutex_lock (client->lock);
130 g_mutex_unlock (client->lock);
158 g_mutex_lock (client->lock);
159 client->broadcasts[broadcastid] =
160 g_list_append (client->broadcasts[broadcastid],
163 g_mutex_unlock (client->lock);
173 uint32_t objid, cmdid;
175 g_return_if_fail (msg);
182 "Ignoring command.");
189 xmms_ipc_register_signal (client, msg, arguments);
191 xmms_ipc_register_broadcast (client, msg, arguments);
204 g_mutex_lock (ipc_object_pool_lock);
205 object = ipc_object_pool->objects[objid];
206 g_mutex_unlock (ipc_object_pool_lock);
212 if (!g_tree_lookup (object->
cmds, GUINT_TO_POINTER (cmdid))) {
218 arg.
args = arguments;
223 xmms_ipc_handle_cmd_value (retmsg, arg.
retval);
245 g_mutex_lock (client->lock);
246 xmms_ipc_client_msg_write (client, retmsg);
247 g_mutex_unlock (client->lock);
257 xmms_ipc_client_read_cb (GIOChannel *iochan,
262 bool disconnect = FALSE;
264 g_return_val_if_fail (client, FALSE);
266 if (cond & G_IO_IN) {
268 if (!client->read_msg) {
274 client->read_msg = NULL;
275 process_msg (client, msg);
283 if (disconnect || (cond & G_IO_HUP)) {
284 if (client->read_msg) {
286 client->read_msg = NULL;
289 g_main_loop_quit (client->ml);
293 if (cond & G_IO_ERR) {
295 g_main_loop_quit (client->ml);
303 xmms_ipc_client_write_cb (GIOChannel *iochan,
308 bool disconnect = FALSE;
310 g_return_val_if_fail (client, FALSE);
315 g_mutex_lock (client->lock);
316 msg = g_queue_peek_head (client->out_msg);
317 g_mutex_unlock (client->lock);
333 g_mutex_lock (client->lock);
334 g_queue_pop_head (client->out_msg);
335 g_mutex_unlock (client->lock);
344 xmms_ipc_client_thread (gpointer data)
351 source = g_io_create_watch (client->iochan, G_IO_IN | G_IO_ERR | G_IO_HUP);
352 g_source_set_callback (source,
353 (GSourceFunc) xmms_ipc_client_read_cb,
356 g_source_attach (source, g_main_loop_get_context (client->ml));
357 g_source_unref (source);
359 g_main_loop_run (client->ml);
361 xmms_ipc_client_destroy (client);
370 GMainContext *context;
373 g_return_val_if_fail (transport, NULL);
377 context = g_main_context_new ();
378 client->ml = g_main_loop_new (context, FALSE);
379 g_main_context_unref (context);
382 client->iochan = g_io_channel_unix_new (fd);
383 g_return_val_if_fail (client->iochan, NULL);
388 g_io_channel_set_encoding (client->iochan, NULL, NULL);
389 g_io_channel_set_buffered (client->iochan, FALSE);
391 client->transport = transport;
393 client->out_msg = g_queue_new ();
394 client->lock = g_mutex_new ();
407 g_mutex_lock (client->ipc->mutex_lock);
408 client->ipc->clients = g_list_remove (client->ipc->clients, client);
409 g_mutex_unlock (client->ipc->mutex_lock);
412 g_main_loop_unref (client->ml);
413 g_io_channel_unref (client->iochan);
417 g_mutex_lock (client->lock);
418 while (!g_queue_is_empty (client->out_msg)) {
423 g_queue_free (client->out_msg);
426 g_list_free (client->broadcasts[i]);
429 g_mutex_unlock (client->lock);
430 g_mutex_free (client->lock);
442 XMMS_DBG (
"Shutting down ipc server threads through config property \"core.ipcsocket\" change.");
456 gboolean queue_empty;
458 g_return_val_if_fail (client, FALSE);
459 g_return_val_if_fail (msg, FALSE);
461 queue_empty = g_queue_is_empty (client->out_msg);
462 g_queue_push_tail (client->out_msg, msg);
466 GMainContext *context = g_main_loop_get_context (client->ml);
467 GSource *source = g_io_create_watch (client->iochan, G_IO_OUT);
469 g_source_set_callback (source,
470 (GSourceFunc) xmms_ipc_client_write_cb,
473 g_source_attach (source, context);
474 g_source_unref (source);
476 g_main_context_wakeup (context);
483 xmms_ipc_source_accept (GIOChannel *chan, GIOCondition cond, gpointer data)
489 if (!(cond & G_IO_IN)) {
501 client = xmms_ipc_client_new (ipc, transport);
507 g_mutex_lock (ipc->mutex_lock);
508 ipc->clients = g_list_append (ipc->clients, client);
509 g_mutex_unlock (ipc->mutex_lock);
514 g_thread_create (xmms_ipc_client_thread, client, FALSE, NULL);
523 xmms_ipc_setup_server_internaly (
xmms_ipc_t *ipc)
525 g_mutex_lock (ipc->mutex_lock);
528 g_io_channel_set_close_on_unref (ipc->chan, TRUE);
529 g_io_channel_set_encoding (ipc->chan, NULL, NULL);
530 g_io_channel_set_buffered (ipc->chan, FALSE);
532 g_io_add_watch (ipc->chan, G_IO_IN | G_IO_HUP | G_IO_ERR,
533 xmms_ipc_source_accept, ipc);
534 g_mutex_unlock (ipc->mutex_lock);
547 g_mutex_lock (ipc_servers_lock);
549 for (s = ipc_servers; s; s = g_list_next (s)) {
551 g_mutex_lock (ipc->mutex_lock);
552 for (c = ipc->clients; c; c = g_list_next (c)) {
554 g_mutex_lock (cli->lock);
555 if (cli->pendingsignals[signalid]) {
556 g_mutex_unlock (cli->lock);
557 g_mutex_unlock (ipc->mutex_lock);
558 g_mutex_unlock (ipc_servers_lock);
561 g_mutex_unlock (cli->lock);
563 g_mutex_unlock (ipc->mutex_lock);
566 g_mutex_unlock (ipc_servers_lock);
574 guint signalid = GPOINTER_TO_UINT (userdata);
578 g_mutex_lock (ipc_servers_lock);
580 for (s = ipc_servers; s && s->data; s = g_list_next (s)) {
582 g_mutex_lock (ipc->mutex_lock);
583 for (c = ipc->clients; c; c = g_list_next (c)) {
585 g_mutex_lock (cli->lock);
586 if (cli->pendingsignals[signalid]) {
589 xmms_ipc_handle_cmd_value (msg, arg);
590 xmms_ipc_client_msg_write (cli, msg);
591 cli->pendingsignals[signalid] = 0;
593 g_mutex_unlock (cli->lock);
595 g_mutex_unlock (ipc->mutex_lock);
598 g_mutex_unlock (ipc_servers_lock);
606 guint broadcastid = GPOINTER_TO_UINT (userdata);
611 g_mutex_lock (ipc_servers_lock);
613 for (s = ipc_servers; s && s->data; s = g_list_next (s)) {
615 g_mutex_lock (ipc->mutex_lock);
616 for (c = ipc->clients; c; c = g_list_next (c)) {
619 g_mutex_lock (cli->lock);
620 for (l = cli->broadcasts[broadcastid]; l; l = g_list_next (l)) {
623 xmms_ipc_handle_cmd_value (msg, arg);
624 xmms_ipc_client_msg_write (cli, msg);
626 g_mutex_unlock (cli->lock);
628 g_mutex_unlock (ipc->mutex_lock);
630 g_mutex_unlock (ipc_servers_lock);
639 g_return_if_fail (
object);
640 g_mutex_lock (ipc_object_pool_lock);
642 ipc_object_pool->broadcasts[signalid] = object;
643 xmms_object_connect (
object, signalid, xmms_ipc_broadcast_cb, GUINT_TO_POINTER (signalid));
645 g_mutex_unlock (ipc_object_pool_lock);
656 g_mutex_lock (ipc_object_pool_lock);
657 obj = ipc_object_pool->broadcasts[signalid];
660 ipc_object_pool->broadcasts[signalid] = NULL;
662 g_mutex_unlock (ipc_object_pool_lock);
671 g_return_if_fail (
object);
673 g_mutex_lock (ipc_object_pool_lock);
674 ipc_object_pool->signals[signalid] = object;
676 g_mutex_unlock (ipc_object_pool_lock);
687 g_mutex_lock (ipc_object_pool_lock);
688 obj = ipc_object_pool->signals[signalid];
691 ipc_object_pool->signals[signalid] = NULL;
693 g_mutex_unlock (ipc_object_pool_lock);
703 g_mutex_lock (ipc_object_pool_lock);
704 ipc_object_pool->objects[objectid] = object;
705 g_mutex_unlock (ipc_object_pool_lock);
714 g_mutex_lock (ipc_object_pool_lock);
715 ipc_object_pool->objects[objectid] = NULL;
716 g_mutex_unlock (ipc_object_pool_lock);
725 ipc_servers_lock = g_mutex_new ();
726 ipc_object_pool_lock = g_mutex_new ();
741 g_mutex_lock (ipc->mutex_lock);
742 g_source_remove_by_user_data (ipc);
743 g_io_channel_unref (ipc->chan);
746 for (c = ipc->clients; c; c = g_list_next (c)) {
752 g_list_free (ipc->clients);
753 g_mutex_unlock (ipc->mutex_lock);
754 g_mutex_free (ipc->mutex_lock);
767 GList *s = ipc_servers;
770 g_mutex_lock (ipc_servers_lock);
774 ipc_servers = g_list_remove (ipc_servers, ipc);
775 xmms_ipc_shutdown_server (ipc);
777 g_mutex_unlock (ipc_servers_lock);
790 gint i = 0, num_init = 0;
791 g_return_val_if_fail (path, FALSE);
793 split = g_strsplit (path,
";", 0);
795 for (i = 0; split && split[i]; i++) {
798 XMMS_DBG (
"No IPC server initialized.");
805 xmms_log_error (
"Couldn't setup IPC listening on '%s'.", split[i]);
810 ipc->mutex_lock = g_mutex_new ();
811 ipc->transport = transport;
812 ipc->signals = ipc_object_pool->signals;
813 ipc->broadcasts = ipc_object_pool->broadcasts;
814 ipc->objects = ipc_object_pool->objects;
816 xmms_ipc_setup_server_internaly (ipc);
819 g_mutex_lock (ipc_servers_lock);
820 ipc_servers = g_list_prepend (ipc_servers, ipc);
821 g_mutex_unlock (ipc_servers_lock);