From 0bad84066bc12a370b8f1e54c37f705fad21929b Mon Sep 17 00:00:00 2001 From: Marc Pavot Date: Sat, 22 Nov 2008 13:26:21 +0100 Subject: [PATCH] command: allow clients to subscribe to specific idle events The client may provide the names of idle events as arguments to the "idle" command to inform MPD that it is only interested in these events. --- src/client.c | 29 ++++++++++++----------------- src/client.h | 2 +- src/command.c | 25 +++++++++++++++++++++++-- src/idle.c | 18 ++++++++++++++++++ src/idle.h | 6 ++++++ 5 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/client.c b/src/client.c index ee984641e..fd55b31a8 100644 --- a/src/client.c +++ b/src/client.c @@ -91,6 +91,9 @@ struct client { /** idle flags pending on this client, to be sent as soon as the client enters "idle" */ unsigned idle_flags; + + /** idle flags that the client wants to receive */ + unsigned idle_subscriptions; }; static LIST_HEAD(clients); @@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...) va_end(args); } -static const char *const idle_names[] = { - "database", - "stored_playlist", - "playlist", - "player", - "mixer", - "output", - "options", -}; - /** * Send "idle" response to this client. */ @@ -783,6 +776,7 @@ static void client_idle_notify(struct client *client) { unsigned flags, i; + const char *const* idle_names; assert(client->idle_waiting); assert(client->idle_flags != 0); @@ -791,10 +785,9 @@ client_idle_notify(struct client *client) client->idle_flags = 0; client->idle_waiting = false; - for (i = 0; i < sizeof(idle_names) / sizeof(idle_names[0]); ++i) { - assert(idle_names[i] != NULL); - - if (flags & (1 << i)) + idle_names = idle_get_names(); + for (i = 0; idle_names[i]; ++i) { + if (flags & (1 << i) & client->idle_subscriptions) client_printf(client, "changed: %s\n", idle_names[i]); } @@ -814,20 +807,22 @@ void client_manager_idle_add(unsigned flags) continue; client->idle_flags |= flags; - if (client->idle_waiting) { + if (client->idle_waiting + && (client->idle_flags & client->idle_subscriptions)) { client_idle_notify(client); client_write_output(client); } } } -bool client_idle_wait(struct client *client) +bool client_idle_wait(struct client *client, unsigned flags) { assert(!client->idle_waiting); client->idle_waiting = true; + client->idle_subscriptions = flags; - if (client->idle_flags != 0) { + if (client->idle_flags & client->idle_subscriptions) { client_idle_notify(client); return true; } else diff --git a/src/client.h b/src/client.h index e6661e249..9c7031820 100644 --- a/src/client.h +++ b/src/client.h @@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags); * sent immediately and "true" is returned". If no, it puts the * client into waiting mode and returns false. */ -bool client_idle_wait(struct client *client); +bool client_idle_wait(struct client *client, unsigned flags); #endif diff --git a/src/command.c b/src/command.c index dc71f1d1a..6a9489d92 100644 --- a/src/command.c +++ b/src/command.c @@ -39,6 +39,7 @@ #include "tag_print.h" #include "path.h" #include "os_compat.h" +#include "idle.h" #define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_STATE "state" @@ -1253,8 +1254,28 @@ static enum command_return handle_idle(struct client *client, mpd_unused int argc, mpd_unused char *argv[]) { + unsigned flags = 0, j; + int i; + const char *const* idle_names; + + idle_names = idle_get_names(); + for (i = 1; i < argc; ++i) { + if (!argv[i]) + continue; + + for (j = 0; idle_names[j]; ++j) { + if (!strcasecmp(argv[i], idle_names[j])) { + flags |= (1 << j); + } + } + } + + /* No argument means that the client wants to receive everything */ + if (flags == 0) + flags = ~0; + /* enable "idle" mode on this client */ - client_idle_wait(client); + client_idle_wait(client, flags); /* return value is "1" so the caller won't print "OK" */ return 1; @@ -1280,7 +1301,7 @@ static const struct command commands[] = { { "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput }, { "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput }, { "find", PERMISSION_READ, 2, -1, handle_find }, - { "idle", PERMISSION_READ, 0, 0, handle_idle }, + { "idle", PERMISSION_READ, 0, -1, handle_idle }, { "kill", PERMISSION_ADMIN, -1, -1, handle_kill }, { "list", PERMISSION_READ, 1, -1, handle_list }, { "listall", PERMISSION_READ, 0, 1, handle_listall }, diff --git a/src/idle.c b/src/idle.c index c779d0a91..884086aae 100644 --- a/src/idle.c +++ b/src/idle.c @@ -30,6 +30,18 @@ static unsigned idle_flags; static pthread_mutex_t idle_mutex = PTHREAD_MUTEX_INITIALIZER; +static const char *const idle_names[] = { + "database", + "stored_playlist", + "playlist", + "player", + "mixer", + "output", + "options", + "elapsed", + NULL +}; + void idle_add(unsigned flags) { @@ -54,3 +66,9 @@ idle_get(void) return flags; } + +const char*const* +idle_get_names(void) +{ + return idle_names; +} diff --git a/src/idle.h b/src/idle.h index 69756b153..5079f09db 100644 --- a/src/idle.h +++ b/src/idle.h @@ -61,4 +61,10 @@ idle_add(unsigned flags); unsigned idle_get(void); +/** + * Get idle names + */ +const char*const* +idle_get_names(void); + #endif