summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2017-02-07 16:52:59 +0100
committerMax Kellermann <max@musicpd.org>2017-02-08 09:06:11 +0100
commit29453ba196db55816ee10fa9908c3e3fa0acd40f (patch)
tree894470833ed3f549a6ab4458a734ba8657c771c4 /src
parent599d77643b57246dc877a2bbf65b932575fbf2c7 (diff)
client: add tag_mask attribute
The "tagtypes" command now has several sub commands which can be used to edit that mask.
Diffstat (limited to 'src')
-rw-r--r--src/TagPrint.cxx4
-rw-r--r--src/client/Client.hxx6
-rw-r--r--src/client/Response.cxx6
-rw-r--r--src/client/Response.hxx9
-rw-r--r--src/command/AllCommands.cxx2
-rw-r--r--src/command/ClientCommands.cxx58
-rw-r--r--src/command/OtherCommands.cxx3
-rw-r--r--src/db/DatabasePrint.cxx3
8 files changed, 83 insertions, 8 deletions
diff --git a/src/TagPrint.cxx b/src/TagPrint.cxx
index 1406f669b..61d86a12e 100644
--- a/src/TagPrint.cxx
+++ b/src/TagPrint.cxx
@@ -40,8 +40,10 @@ tag_print(Response &r, TagType type, const char *value)
void
tag_print_values(Response &r, const Tag &tag)
{
+ const auto tag_mask = r.GetTagMask();
for (const auto &i : tag)
- tag_print(r, i.type, i.value);
+ if (tag_mask.Test(i.type))
+ tag_print(r, i.type, i.value);
}
void
diff --git a/src/client/Client.hxx b/src/client/Client.hxx
index 759e611d9..7ce128ce3 100644
--- a/src/client/Client.hxx
+++ b/src/client/Client.hxx
@@ -23,6 +23,7 @@
#include "check.h"
#include "ClientMessage.hxx"
#include "command/CommandListBuilder.hxx"
+#include "tag/Mask.hxx"
#include "event/FullyBufferedSocket.hxx"
#include "event/TimeoutMonitor.hxx"
#include "Compiler.h"
@@ -71,6 +72,11 @@ public:
unsigned idle_subscriptions;
/**
+ * The tags this client is interested in.
+ */
+ TagMask tag_mask = TagMask::All();
+
+ /**
* A list of channel names this client is subscribed to.
*/
std::set<std::string> subscriptions;
diff --git a/src/client/Response.cxx b/src/client/Response.cxx
index 31eb6a78e..b21ac91b5 100644
--- a/src/client/Response.cxx
+++ b/src/client/Response.cxx
@@ -23,6 +23,12 @@
#include "util/FormatString.hxx"
#include "util/AllocatedString.hxx"
+TagMask
+Response::GetTagMask() const
+{
+ return GetClient().tag_mask;
+}
+
bool
Response::Write(const void *data, size_t length)
{
diff --git a/src/client/Response.hxx b/src/client/Response.hxx
index 280dc1d55..a133e96a3 100644
--- a/src/client/Response.hxx
+++ b/src/client/Response.hxx
@@ -22,11 +22,13 @@
#include "check.h"
#include "protocol/Ack.hxx"
+#include "Compiler.h"
#include <stddef.h>
#include <stdarg.h>
class Client;
+class TagMask;
class Response {
Client &client;
@@ -59,6 +61,13 @@ public:
return client;
}
+ /**
+ * Accessor for Client::tag_mask. Can be used if caller wants
+ * to avoid including Client.hxx.
+ */
+ gcc_pure
+ TagMask GetTagMask() const;
+
void SetCommand(const char *_command) {
command = _command;
}
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx
index 7d65898dd..45aed51ad 100644
--- a/src/command/AllCommands.cxx
+++ b/src/command/AllCommands.cxx
@@ -187,7 +187,7 @@ static constexpr struct command commands[] = {
{ "subscribe", PERMISSION_READ, 1, 1, handle_subscribe },
{ "swap", PERMISSION_CONTROL, 2, 2, handle_swap },
{ "swapid", PERMISSION_CONTROL, 2, 2, handle_swapid },
- { "tagtypes", PERMISSION_READ, 0, 0, handle_tagtypes },
+ { "tagtypes", PERMISSION_READ, 0, -1, handle_tagtypes },
{ "toggleoutput", PERMISSION_ADMIN, 1, 1, handle_toggleoutput },
#ifdef ENABLE_DATABASE
{ "unmount", PERMISSION_ADMIN, 1, 1, handle_unmount },
diff --git a/src/command/ClientCommands.cxx b/src/command/ClientCommands.cxx
index 3aa89b0e6..c5f70b94d 100644
--- a/src/command/ClientCommands.cxx
+++ b/src/command/ClientCommands.cxx
@@ -24,6 +24,8 @@
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "TagPrint.hxx"
+#include "tag/ParseName.hxx"
+#include "util/StringAPI.hxx"
CommandResult
handle_close(gcc_unused Client &client, gcc_unused Request args,
@@ -53,10 +55,58 @@ handle_password(Client &client, Request args, Response &r)
return CommandResult::OK;
}
+static TagMask
+ParseTagMask(Request request)
+{
+ if (request.IsEmpty())
+ throw ProtocolError(ACK_ERROR_ARG, "Not enough arguments");
+
+ TagMask result = TagMask::None();
+
+ for (const char *name : request) {
+ auto type = tag_name_parse_i(name);
+ if (type == TAG_NUM_OF_ITEM_TYPES)
+ throw ProtocolError(ACK_ERROR_ARG, "Unknown tag type");
+
+ result |= type;
+ }
+
+ return result;
+}
+
CommandResult
-handle_tagtypes(gcc_unused Client &client, gcc_unused Request request,
- Response &r)
+handle_tagtypes(Client &client, Request request, Response &r)
{
- tag_print_types(r);
- return CommandResult::OK;
+ if (request.IsEmpty()) {
+ tag_print_types(r);
+ return CommandResult::OK;
+ }
+
+ const char *cmd = request.shift();
+ if (StringIsEqual(cmd, "all")) {
+ if (!request.IsEmpty()) {
+ r.Error(ACK_ERROR_ARG, "Too many arguments");
+ return CommandResult::ERROR;
+ }
+
+ client.tag_mask = TagMask::All();
+ return CommandResult::OK;
+ } else if (StringIsEqual(cmd, "clear")) {
+ if (!request.IsEmpty()) {
+ r.Error(ACK_ERROR_ARG, "Too many arguments");
+ return CommandResult::ERROR;
+ }
+
+ client.tag_mask = TagMask::None();
+ return CommandResult::OK;
+ } else if (StringIsEqual(cmd, "enable")) {
+ client.tag_mask |= ParseTagMask(request);
+ return CommandResult::OK;
+ } else if (StringIsEqual(cmd, "disable")) {
+ client.tag_mask &= ~ParseTagMask(request);
+ return CommandResult::OK;
+ } else {
+ r.Error(ACK_ERROR_ARG, "Unknown sub command");
+ return CommandResult::ERROR;
+ }
}
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index 48487fe8e..013d4dff2 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
@@ -97,7 +97,8 @@ print_tag(TagType type, const char *value, void *ctx)
{
auto &r = *(Response *)ctx;
- tag_print(r, type, value);
+ if (r.GetClient().tag_mask.Test(type))
+ tag_print(r, type, value);
}
CommandResult
diff --git a/src/db/DatabasePrint.cxx b/src/db/DatabasePrint.cxx
index b5e0b69f7..31f971cd8 100644
--- a/src/db/DatabasePrint.cxx
+++ b/src/db/DatabasePrint.cxx
@@ -196,8 +196,9 @@ PrintUniqueTag(Response &r, TagType tag_type,
assert(value != nullptr);
tag_print(r, tag_type, value);
+ const auto tag_mask = r.GetTagMask();
for (const auto &item : tag)
- if (item.type != tag_type)
+ if (item.type != tag_type && tag_mask.Test(item.type))
tag_print(r, item.type, item.value);
}