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);
#define xmms_error_isok(e)
xmms_ipc_t * xmms_ipc_init(void)
Initialize IPC.
void xmms_ipc_msg_set_cookie(xmms_ipc_msg_t *msg, uint32_t cookie)
void xmms_set_thread_name(const gchar *name)
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed...
xmms_ipc_msg_t * xmms_ipc_msg_alloc(void)
xmms_socket_t xmms_ipc_transport_fd_get(xmms_ipc_transport_t *ipct)
void on_config_ipcsocket_change(xmms_object_t *object, xmmsv_t *_data, gpointer udata)
Gets called when the config property "core.ipcsocket" has changed.
gboolean xmms_ipc_has_pending(guint signalid)
Checks if someone is waiting for signalid.
xmmsv_t * xmmsv_new_error(const char *errstr)
Allocates a new error xmmsv_t.
bool xmms_ipc_msg_get_value(xmms_ipc_msg_t *msg, xmmsv_t **val)
uint32_t xmms_ipc_msg_get_cmd(const xmms_ipc_msg_t *msg)
void xmms_ipc_broadcast_register(xmms_object_t *object, xmms_ipc_signals_t signalid)
Register a broadcast signal.
int xmmsv_get_int(const xmmsv_t *val, int32_t *r)
Retrieves a signed integer from the value.
gboolean xmms_ipc_setup_server(const gchar *path)
Start the server.
void xmms_ipc_signal_register(xmms_object_t *object, xmms_ipc_signals_t signalid)
Register a signal.
const gchar * xmms_error_message_get(xmms_error_t *err)
Get the human readable error.
void xmms_ipc_msg_destroy(xmms_ipc_msg_t *msg)
struct xmms_ipc_msg_St xmms_ipc_msg_t
struct xmms_ipc_client_St xmms_ipc_client_t
A IPC client representation.
xmms_ipc_msg_t * xmms_ipc_msg_new(uint32_t object, uint32_t cmd)
#define xmms_log_error(fmt,...)
void xmms_object_cmd_arg_init(xmms_object_cmd_arg_t *arg)
Initialize a command argument.
bool xmms_ipc_msg_write_transport(xmms_ipc_msg_t *msg, xmms_ipc_transport_t *transport, bool *disconnected)
Try to write message to transport.
int xmmsv_list_get(xmmsv_t *listv, int pos, xmmsv_t **val)
Get the element at the given position in the list xmmsv_t.
void xmms_object_cmd_call(xmms_object_t *object, guint cmdid, xmms_object_cmd_arg_t *arg)
Call a command with argument.
struct xmms_ipc_object_pool_t xmms_ipc_object_pool_t
The IPC object list.
xmms_ipc_transport_t * xmms_ipc_server_init(const char *path)
const gchar * xmms_config_property_get_string(const xmms_config_property_t *prop)
Return the value of a config property as a string.
void xmms_ipc_signal_unregister(xmms_ipc_signals_t signalid)
Unregister a signal.
void xmms_ipc_object_unregister(xmms_ipc_objects_t objectid)
Remove a object from the IPC core.
xmms_ipc_transport_t * xmms_ipc_server_accept(xmms_ipc_transport_t *ipct)
uint32_t xmms_ipc_msg_put_value(xmms_ipc_msg_t *msg, xmmsv_t *v)
#define xmms_log_info(fmt,...)
bool xmms_ipc_msg_read_transport(xmms_ipc_msg_t *msg, xmms_ipc_transport_t *transport, bool *disconnected)
Try to read message from transport into msg.
uint32_t xmms_ipc_msg_get_object(const xmms_ipc_msg_t *msg)
void xmms_ipc_shutdown(void)
Disable IPC.
#define XMMS_DBG(fmt,...)
void xmms_object_connect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Connect to a signal that is emitted by this object.
struct xmms_ipc_St xmms_ipc_t
void xmms_ipc_broadcast_unregister(xmms_ipc_signals_t signalid)
Unregister a broadcast signal.
void xmms_object_disconnect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Disconnect from a signal.
struct xmms_config_property_St xmms_config_property_t
void xmms_ipc_object_register(xmms_ipc_objects_t objectid, xmms_object_t *object)
Register a object to the IPC core.
void xmms_ipc_transport_destroy(xmms_ipc_transport_t *ipct)
uint32_t xmms_ipc_msg_get_cookie(const xmms_ipc_msg_t *msg)