aboutsummaryrefslogtreecommitdiffstats
path: root/src/command
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2015-08-06 22:10:25 +0200
committerMax Kellermann <max@duempel.org>2015-08-12 08:41:05 +0200
commit7652a2986b0d0ad55b2776685130f1c68d7108c7 (patch)
treeb4d45e60e97757454f1ff8e4dc793a1e7d852c36 /src/command
parentb1480167be487d09ff46bb86ad02041fb28acff1 (diff)
downloadmpd-7652a2986b0d0ad55b2776685130f1c68d7108c7.tar.gz
mpd-7652a2986b0d0ad55b2776685130f1c68d7108c7.tar.xz
mpd-7652a2986b0d0ad55b2776685130f1c68d7108c7.zip
client/Response: new Client wrapper class for writing responses
Diffstat (limited to 'src/command')
-rw-r--r--src/command/AllCommands.cxx65
-rw-r--r--src/command/CommandError.cxx55
-rw-r--r--src/command/CommandError.hxx6
-rw-r--r--src/command/DatabaseCommands.cxx82
-rw-r--r--src/command/FileCommands.cxx72
-rw-r--r--src/command/MessageCommands.cxx34
-rw-r--r--src/command/NeighborCommands.cxx16
-rw-r--r--src/command/OtherCommands.cxx117
-rw-r--r--src/command/OutputCommands.cxx29
-rw-r--r--src/command/PlayerCommands.cxx187
-rw-r--r--src/command/PlaylistCommands.cxx75
-rw-r--r--src/command/QueueCommands.cxx132
-rw-r--r--src/command/Request.hxx14
-rw-r--r--src/command/StickerCommands.cxx69
-rw-r--r--src/command/StorageCommands.cxx76
-rw-r--r--src/command/StorageCommands.hxx5
-rw-r--r--src/command/TagCommands.cxx19
17 files changed, 588 insertions, 465 deletions
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx
index 9f0b0a606..57d4db983 100644
--- a/src/command/AllCommands.cxx
+++ b/src/command/AllCommands.cxx
@@ -36,6 +36,7 @@
#include "protocol/Result.hxx"
#include "Partition.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "util/Macros.hxx"
#include "util/Tokenizer.hxx"
#include "util/Error.hxx"
@@ -226,38 +227,50 @@ command_available(gcc_unused const Partition &partition,
return true;
}
-/* don't be fooled, this is the command handler for "commands" command */
static CommandResult
-handle_commands(Client &client, gcc_unused Request args)
+PrintAvailableCommands(Response &r, const Partition &partition,
+ unsigned permission)
{
- const unsigned permission = client.GetPermission();
-
for (unsigned i = 0; i < num_commands; ++i) {
const struct command *cmd = &commands[i];
if (cmd->permission == (permission & cmd->permission) &&
- command_available(client.partition, cmd))
- client_printf(client, "command: %s\n", cmd->cmd);
+ command_available(partition, cmd))
+ r.Format("command: %s\n", cmd->cmd);
}
return CommandResult::OK;
}
static CommandResult
-handle_not_commands(Client &client, gcc_unused Request args)
+PrintUnavailableCommands(Response &r, unsigned permission)
{
- const unsigned permission = client.GetPermission();
-
for (unsigned i = 0; i < num_commands; ++i) {
const struct command *cmd = &commands[i];
if (cmd->permission != (permission & cmd->permission))
- client_printf(client, "command: %s\n", cmd->cmd);
+ r.Format("command: %s\n", cmd->cmd);
}
return CommandResult::OK;
}
+/* don't be fooled, this is the command handler for "commands" command */
+static CommandResult
+handle_commands(Client &client, gcc_unused Request args)
+{
+ Response r(client);
+ return PrintAvailableCommands(r, client.partition,
+ client.GetPermission());
+}
+
+static CommandResult
+handle_not_commands(Client &client, gcc_unused Request args)
+{
+ Response r(client);
+ return PrintUnavailableCommands(r, client.GetPermission());
+}
+
void
command_init()
{
@@ -299,7 +312,8 @@ command_check_request(const struct command *cmd, Client &client,
unsigned permission, Request args)
{
if (cmd->permission != (permission & cmd->permission)) {
- command_error(client, ACK_ERROR_PERMISSION,
+ Response r(client);
+ r.FormatError(ACK_ERROR_PERMISSION,
"you don't have permission for \"%s\"",
cmd->cmd);
return false;
@@ -312,16 +326,19 @@ command_check_request(const struct command *cmd, Client &client,
return true;
if (min == max && unsigned(max) != args.size) {
- command_error(client, ACK_ERROR_ARG,
+ Response r(client);
+ r.FormatError(ACK_ERROR_ARG,
"wrong number of arguments for \"%s\"",
cmd->cmd);
return false;
} else if (args.size < unsigned(min)) {
- command_error(client, ACK_ERROR_ARG,
+ Response r(client);
+ r.FormatError(ACK_ERROR_ARG,
"too few arguments for \"%s\"", cmd->cmd);
return false;
} else if (max >= 0 && args.size > unsigned(max)) {
- command_error(client, ACK_ERROR_ARG,
+ Response r(client);
+ r.FormatError(ACK_ERROR_ARG,
"too many arguments for \"%s\"", cmd->cmd);
return false;
} else
@@ -336,7 +353,8 @@ command_checked_lookup(Client &client, unsigned permission,
const struct command *cmd = command_lookup(cmd_name);
if (cmd == nullptr) {
- command_error(client, ACK_ERROR_UNKNOWN,
+ Response r(client);
+ r.FormatError(ACK_ERROR_UNKNOWN,
"unknown command \"%s\"", cmd_name);
return nullptr;
}
@@ -357,7 +375,7 @@ command_process(Client &client, unsigned num, char *line)
command_list_num = num;
/* get the command name (first word on the line) */
- /* we have to set current_command because command_error()
+ /* we have to set current_command because Response::Error()
expects it to be set */
Tokenizer tokenizer(line);
@@ -366,12 +384,12 @@ command_process(Client &client, unsigned num, char *line)
tokenizer.NextWord(error);
if (cmd_name == nullptr) {
current_command = "";
+
+ Response r(client);
if (tokenizer.IsEnd())
- command_error(client, ACK_ERROR_UNKNOWN,
- "No command given");
+ r.FormatError(ACK_ERROR_UNKNOWN, "No command given");
else
- command_error(client, ACK_ERROR_UNKNOWN,
- "%s", error.GetMessage());
+ r.Error(ACK_ERROR_UNKNOWN, error.GetMessage());
current_command = nullptr;
@@ -387,8 +405,8 @@ command_process(Client &client, unsigned num, char *line)
while (true) {
if (args.size == COMMAND_ARGV_MAX) {
- command_error(client, ACK_ERROR_ARG,
- "Too many arguments");
+ Response r(client);
+ r.Error(ACK_ERROR_ARG, "Too many arguments");
current_command = nullptr;
return CommandResult::ERROR;
}
@@ -398,7 +416,8 @@ command_process(Client &client, unsigned num, char *line)
if (tokenizer.IsEnd())
break;
- command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage());
+ Response r(client);
+ r.Error(ACK_ERROR_UNKNOWN, error.GetMessage());
current_command = nullptr;
return CommandResult::ERROR;
}
diff --git a/src/command/CommandError.cxx b/src/command/CommandError.cxx
index da0571295..d95722c3b 100644
--- a/src/command/CommandError.cxx
+++ b/src/command/CommandError.cxx
@@ -20,7 +20,7 @@
#include "config.h"
#include "CommandError.hxx"
#include "db/DatabaseError.hxx"
-#include "protocol/Result.hxx"
+#include "client/Response.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
@@ -29,57 +29,55 @@
#include <errno.h>
CommandResult
-print_playlist_result(Client &client, PlaylistResult result)
+print_playlist_result(Response &r, PlaylistResult result)
{
switch (result) {
case PlaylistResult::SUCCESS:
return CommandResult::OK;
case PlaylistResult::ERRNO:
- command_error(client, ACK_ERROR_SYSTEM, "%s",
- strerror(errno));
+ r.Error(ACK_ERROR_SYSTEM, strerror(errno));
return CommandResult::ERROR;
case PlaylistResult::DENIED:
- command_error(client, ACK_ERROR_PERMISSION, "Access denied");
+ r.Error(ACK_ERROR_PERMISSION, "Access denied");
return CommandResult::ERROR;
case PlaylistResult::NO_SUCH_SONG:
- command_error(client, ACK_ERROR_NO_EXIST, "No such song");
+ r.Error(ACK_ERROR_NO_EXIST, "No such song");
return CommandResult::ERROR;
case PlaylistResult::NO_SUCH_LIST:
- command_error(client, ACK_ERROR_NO_EXIST, "No such playlist");
+ r.Error(ACK_ERROR_NO_EXIST, "No such playlist");
return CommandResult::ERROR;
case PlaylistResult::LIST_EXISTS:
- command_error(client, ACK_ERROR_EXIST,
- "Playlist already exists");
+ r.Error(ACK_ERROR_EXIST, "Playlist already exists");
return CommandResult::ERROR;
case PlaylistResult::BAD_NAME:
- command_error(client, ACK_ERROR_ARG,
- "playlist name is invalid: "
- "playlist names may not contain slashes,"
- " newlines or carriage returns");
+ r.Error(ACK_ERROR_ARG,
+ "playlist name is invalid: "
+ "playlist names may not contain slashes,"
+ " newlines or carriage returns");
return CommandResult::ERROR;
case PlaylistResult::BAD_RANGE:
- command_error(client, ACK_ERROR_ARG, "Bad song index");
+ r.Error(ACK_ERROR_ARG, "Bad song index");
return CommandResult::ERROR;
case PlaylistResult::NOT_PLAYING:
- command_error(client, ACK_ERROR_PLAYER_SYNC, "Not playing");
+ r.Error(ACK_ERROR_PLAYER_SYNC, "Not playing");
return CommandResult::ERROR;
case PlaylistResult::TOO_LARGE:
- command_error(client, ACK_ERROR_PLAYLIST_MAX,
- "playlist is at the max size");
+ r.Error(ACK_ERROR_PLAYLIST_MAX,
+ "playlist is at the max size");
return CommandResult::ERROR;
case PlaylistResult::DISABLED:
- command_error(client, ACK_ERROR_UNKNOWN,
- "stored playlist support is disabled");
+ r.Error(ACK_ERROR_UNKNOWN,
+ "stored playlist support is disabled");
return CommandResult::ERROR;
}
@@ -88,42 +86,39 @@ print_playlist_result(Client &client, PlaylistResult result)
}
CommandResult
-print_error(Client &client, const Error &error)
+print_error(Response &r, const Error &error)
{
assert(error.IsDefined());
LogError(error);
if (error.IsDomain(playlist_domain)) {
- return print_playlist_result(client,
+ return print_playlist_result(r,
PlaylistResult(error.GetCode()));
} else if (error.IsDomain(ack_domain)) {
- command_error(client, (ack)error.GetCode(),
- "%s", error.GetMessage());
+ r.Error((ack)error.GetCode(), error.GetMessage());
return CommandResult::ERROR;
#ifdef ENABLE_DATABASE
} else if (error.IsDomain(db_domain)) {
switch ((enum db_error)error.GetCode()) {
case DB_DISABLED:
- command_error(client, ACK_ERROR_NO_EXIST, "%s",
- error.GetMessage());
+ r.Error(ACK_ERROR_NO_EXIST, error.GetMessage());
return CommandResult::ERROR;
case DB_NOT_FOUND:
- command_error(client, ACK_ERROR_NO_EXIST, "Not found");
+ r.Error(ACK_ERROR_NO_EXIST, "Not found");
return CommandResult::ERROR;
case DB_CONFLICT:
- command_error(client, ACK_ERROR_ARG, "Conflict");
+ r.Error(ACK_ERROR_ARG, "Conflict");
return CommandResult::ERROR;
}
#endif
} else if (error.IsDomain(errno_domain)) {
- command_error(client, ACK_ERROR_SYSTEM, "%s",
- strerror(error.GetCode()));
+ r.Error(ACK_ERROR_SYSTEM, strerror(error.GetCode()));
return CommandResult::ERROR;
}
- command_error(client, ACK_ERROR_UNKNOWN, "error");
+ r.Error(ACK_ERROR_UNKNOWN, "error");
return CommandResult::ERROR;
}
diff --git a/src/command/CommandError.hxx b/src/command/CommandError.hxx
index 6c42ed960..e33386078 100644
--- a/src/command/CommandError.hxx
+++ b/src/command/CommandError.hxx
@@ -23,16 +23,16 @@
#include "CommandResult.hxx"
#include "PlaylistError.hxx"
-class Client;
+class Response;
class Error;
CommandResult
-print_playlist_result(Client &client, PlaylistResult result);
+print_playlist_result(Response &r, PlaylistResult result);
/**
* Send the #Error to the client.
*/
CommandResult
-print_error(Client &client, const Error &error);
+print_error(Response &r, const Error &error);
#endif
diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx
index 6e6f3399b..62764139e 100644
--- a/src/command/DatabaseCommands.cxx
+++ b/src/command/DatabaseCommands.cxx
@@ -28,11 +28,11 @@
#include "db/Selection.hxx"
#include "CommandError.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "tag/Tag.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "SongFilter.hxx"
-#include "protocol/Result.hxx"
#include "BulkEdit.hxx"
#include <string.h>
@@ -40,11 +40,13 @@
CommandResult
handle_listfiles_db(Client &client, const char *uri)
{
+ Response r(client);
const DatabaseSelection selection(uri, false);
Error error;
- if (!db_selection_print(client, selection, false, true, error))
- return print_error(client, error);
+ if (!db_selection_print(r, client.partition,
+ selection, false, true, error))
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -52,14 +54,17 @@ handle_listfiles_db(Client &client, const char *uri)
CommandResult
handle_lsinfo2(Client &client, Request args)
{
+ Response r(client);
+
/* default is root directory */
const auto uri = args.GetOptional(0, "");
const DatabaseSelection selection(uri, false);
Error error;
- if (!db_selection_print(client, selection, true, false, error))
- return print_error(client, error);
+ if (!db_selection_print(r, client.partition,
+ selection, true, false, error))
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -67,9 +72,11 @@ handle_lsinfo2(Client &client, Request args)
static CommandResult
handle_match(Client &client, Request args, bool fold_case)
{
+ Response r(client);
+
RangeArg window;
if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) {
- if (!args.Parse(args.size - 1, window, client))
+ if (!args.Parse(args.size - 1, window, r))
return CommandResult::ERROR;
args.pop_back();
@@ -79,17 +86,18 @@ handle_match(Client &client, Request args, bool fold_case)
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
- command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ r.Error(ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
const DatabaseSelection selection("", true, &filter);
Error error;
- return db_selection_print(client, selection, true, false,
+ return db_selection_print(r, client.partition,
+ selection, true, false,
window.start, window.end, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
@@ -107,9 +115,11 @@ handle_search(Client &client, Request args)
static CommandResult
handle_match_add(Client &client, Request args, bool fold_case)
{
+ Response r(client);
+
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
- command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ r.Error(ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
@@ -119,7 +129,7 @@ handle_match_add(Client &client, Request args, bool fold_case)
Error error;
return AddFromDatabase(client.partition, selection, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
@@ -137,34 +147,38 @@ handle_searchadd(Client &client, Request args)
CommandResult
handle_searchaddpl(Client &client, Request args)
{
+ Response r(client);
+
const char *playlist = args.shift();
SongFilter filter;
if (!filter.Parse(args, true)) {
- command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ r.Error(ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
Error error;
const Database *db = client.GetDatabase(error);
if (db == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
return search_add_to_playlist(*db, *client.GetStorage(),
"", playlist, &filter, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_count(Client &client, Request args)
{
+ Response r(client);
+
TagType group = TAG_NUM_OF_ITEM_TYPES;
if (args.size >= 2 && strcmp(args[args.size - 2], "group") == 0) {
const char *s = args[args.size - 1];
group = tag_name_parse_i(s);
if (group == TAG_NUM_OF_ITEM_TYPES) {
- command_error(client, ACK_ERROR_ARG,
+ r.FormatError(ACK_ERROR_ARG,
"Unknown tag type: %s", s);
return CommandResult::ERROR;
}
@@ -175,38 +189,43 @@ handle_count(Client &client, Request args)
SongFilter filter;
if (!args.IsEmpty() && !filter.Parse(args, false)) {
- command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ r.Error(ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
Error error;
- return PrintSongCount(client, "", &filter, group, error)
+ return PrintSongCount(r, client.partition, "", &filter, group, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_listall(Client &client, Request args)
{
+ Response r(client);
+
/* default is root directory */
const auto uri = args.GetOptional(0, "");
Error error;
- return db_selection_print(client, DatabaseSelection(uri, true),
+ return db_selection_print(r, client.partition,
+ DatabaseSelection(uri, true),
false, false, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_list(Client &client, Request args)
{
+ Response r(client);
+
const char *tag_name = args.shift();
unsigned tagType = locate_parse_type(tag_name);
if (tagType >= TAG_NUM_OF_ITEM_TYPES &&
tagType != LOCATE_TAG_FILE_TYPE) {
- command_error(client, ACK_ERROR_ARG,
+ r.FormatError(ACK_ERROR_ARG,
"Unknown tag type: %s", tag_name);
return CommandResult::ERROR;
}
@@ -217,7 +236,7 @@ handle_list(Client &client, Request args)
if (args.size == 1) {
/* for compatibility with < 0.12.0 */
if (tagType != TAG_ALBUM) {
- command_error(client, ACK_ERROR_ARG,
+ r.FormatError(ACK_ERROR_ARG,
"should be \"%s\" for 3 arguments",
tag_item_names[TAG_ALBUM]);
return CommandResult::ERROR;
@@ -231,7 +250,7 @@ handle_list(Client &client, Request args)
const char *s = args[args.size - 1];
TagType gt = tag_name_parse_i(s);
if (gt == TAG_NUM_OF_ITEM_TYPES) {
- command_error(client, ACK_ERROR_ARG,
+ r.FormatError(ACK_ERROR_ARG,
"Unknown tag type: %s", s);
return CommandResult::ERROR;
}
@@ -246,8 +265,7 @@ handle_list(Client &client, Request args)
filter = new SongFilter();
if (!filter->Parse(args, false)) {
delete filter;
- command_error(client, ACK_ERROR_ARG,
- "not able to parse args");
+ r.Error(ACK_ERROR_ARG, "not able to parse args");
return CommandResult::ERROR;
}
}
@@ -255,15 +273,16 @@ handle_list(Client &client, Request args)
if (tagType < TAG_NUM_OF_ITEM_TYPES &&
group_mask & (1u << tagType)) {
delete filter;
- command_error(client, ACK_ERROR_ARG, "Conflicting group");
+ r.Error(ACK_ERROR_ARG, "Conflicting group");
return CommandResult::ERROR;
}
Error error;
CommandResult ret =
- PrintUniqueTags(client, tagType, group_mask, filter, error)
+ PrintUniqueTags(r, client.partition,
+ tagType, group_mask, filter, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
delete filter;
@@ -273,12 +292,15 @@ handle_list(Client &client, Request args)
CommandResult
handle_listallinfo(Client &client, Request args)
{
+ Response r(client);
+
/* default is root directory */
const auto uri = args.GetOptional(0, "");
Error error;
- return db_selection_print(client, DatabaseSelection(uri, true),
+ return db_selection_print(r, client.partition,
+ DatabaseSelection(uri, true),
true, false, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index 574254d7a..c30dad8c8 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
@@ -24,8 +24,8 @@
#include "Request.hxx"
#include "CommandError.hxx"
#include "protocol/Ack.hxx"
-#include "protocol/Result.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "util/ConstBuffer.hxx"
#include "util/CharUtil.hxx"
#include "util/UriUtil.hxx"
@@ -72,21 +72,22 @@ skip_path(Path name_fs)
CommandResult
handle_listfiles_local(Client &client, const char *path_utf8)
{
+ Response r(client);
+
const auto path_fs = AllocatedPath::FromUTF8(path_utf8);
if (path_fs.IsNull()) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "unsupported file name");
+ r.Error(ACK_ERROR_NO_EXIST, "unsupported file name");
return CommandResult::ERROR;
}
Error error;
if (!client.AllowFile(path_fs, error))
- return print_error(client, error);
+ return print_error(r, error);
DirectoryReader reader(path_fs);
if (reader.HasFailed()) {
error.FormatErrno("Failed to open '%s'", path_utf8);
- return print_error(client, error);
+ return print_error(r, error);
}
while (reader.ReadEntry()) {
@@ -105,17 +106,16 @@ handle_listfiles_local(Client &client, const char *path_utf8)
continue;
if (fi.IsRegular())
- client_printf(client, "file: %s\n"
- "size: %" PRIu64 "\n",
- name_utf8.c_str(),
- fi.GetSize());
+ r.Format("file: %s\n"
+ "size: %" PRIu64 "\n",
+ name_utf8.c_str(),
+ fi.GetSize());
else if (fi.IsDirectory())
- client_printf(client, "directory: %s\n",
- name_utf8.c_str());
+ r.Format("directory: %s\n", name_utf8.c_str());
else
continue;
- time_print(client, "Last-Modified", fi.GetModificationTime());
+ time_print(r, "Last-Modified", fi.GetModificationTime());
}
return CommandResult::OK;
@@ -158,10 +158,10 @@ IsValidValue(const char *p)
static void
print_pair(const char *key, const char *value, void *ctx)
{
- Client &client = *(Client *)ctx;
+ auto &r = *(Response *)ctx;
if (IsValidName(key) && IsValidValue(value))
- client_printf(client, "%s: %s\n", key, value);
+ r.Format("%s: %s\n", key, value);
}
static constexpr tag_handler print_comment_handler = {
@@ -171,17 +171,15 @@ static constexpr tag_handler print_comment_handler = {
};
static CommandResult
-read_stream_comments(Client &client, const char *uri)
+read_stream_comments(Response &r, const char *uri)
{
if (!uri_supported_scheme(uri)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "unsupported URI scheme");
+ r.Error(ACK_ERROR_NO_EXIST, "unsupported URI scheme");
return CommandResult::ERROR;
}
- if (!tag_stream_scan(uri, print_comment_handler, &client)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "Failed to load file");
+ if (!tag_stream_scan(uri, print_comment_handler, &r)) {
+ r.Error(ACK_ERROR_NO_EXIST, "Failed to load file");
return CommandResult::ERROR;
}
@@ -190,16 +188,15 @@ read_stream_comments(Client &client, const char *uri)
}
static CommandResult
-read_file_comments(Client &client, const Path path_fs)
+read_file_comments(Response &r, const Path path_fs)
{
- if (!tag_file_scan(path_fs, print_comment_handler, &client)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "Failed to load file");
+ if (!tag_file_scan(path_fs, print_comment_handler, &r)) {
+ r.Error(ACK_ERROR_NO_EXIST, "Failed to load file");
return CommandResult::ERROR;
}
- tag_ape_scan2(path_fs, &print_comment_handler, &client);
- tag_id3_scan(path_fs, &print_comment_handler, &client);
+ tag_ape_scan2(path_fs, &print_comment_handler, &r);
+ tag_id3_scan(path_fs, &print_comment_handler, &r);
return CommandResult::OK;
@@ -219,6 +216,8 @@ translate_uri(const char *uri)
CommandResult
handle_read_comments(Client &client, Request args)
{
+ Response r(client);
+
assert(args.size == 1);
const char *const uri = translate_uri(args.front());
@@ -227,25 +226,23 @@ handle_read_comments(Client &client, Request args)
const char *path_utf8 = uri + 7;
AllocatedPath path_fs = AllocatedPath::FromUTF8(path_utf8);
if (path_fs.IsNull()) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "unsupported file name");
+ r.Error(ACK_ERROR_NO_EXIST, "unsupported file name");
return CommandResult::ERROR;
}
Error error;
if (!client.AllowFile(path_fs, error))
- return print_error(client, error);
+ return print_error(r, error);
- return read_file_comments(client, path_fs);
+ return read_file_comments(r, path_fs);
} else if (uri_has_scheme(uri)) {
- return read_stream_comments(client, uri);
+ return read_stream_comments(r, uri);
} else if (!PathTraitsUTF8::IsAbsolute(uri)) {
#ifdef ENABLE_DATABASE
const Storage *storage = client.GetStorage();
if (storage == nullptr) {
#endif
- command_error(client, ACK_ERROR_NO_EXIST,
- "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
#ifdef ENABLE_DATABASE
}
@@ -253,21 +250,20 @@ handle_read_comments(Client &client, Request args)
{
AllocatedPath path_fs = storage->MapFS(uri);
if (!path_fs.IsNull())
- return read_file_comments(client, path_fs);
+ return read_file_comments(r, path_fs);
}
{
const std::string uri2 = storage->MapUTF8(uri);
if (uri_has_scheme(uri2.c_str()))
- return read_stream_comments(client,
- uri2.c_str());
+ return read_stream_comments(r, uri2.c_str());
}
- command_error(client, ACK_ERROR_NO_EXIST, "No such file");
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
return CommandResult::ERROR;
#endif
} else {
- command_error(client, ACK_ERROR_NO_EXIST, "No such file");
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
return CommandResult::ERROR;
}
}
diff --git a/src/command/MessageCommands.cxx b/src/command/MessageCommands.cxx
index 24c9ddf2d..62d47ff0e 100644
--- a/src/command/MessageCommands.cxx
+++ b/src/command/MessageCommands.cxx
@@ -22,9 +22,9 @@
#include "Request.hxx"
#include "client/Client.hxx"
#include "client/ClientList.hxx"
+#include "client/Response.hxx"
#include "Instance.hxx"
#include "Partition.hxx"
-#include "protocol/Result.hxx"
#include "util/ConstBuffer.hxx"
#include <set>
@@ -35,6 +35,8 @@
CommandResult
handle_subscribe(Client &client, Request args)
{
+ Response r(client);
+
assert(args.size == 1);
const char *const channel_name = args[0];
@@ -43,18 +45,15 @@ handle_subscribe(Client &client, Request args)
return CommandResult::OK;
case Client::SubscribeResult::INVALID:
- command_error(client, ACK_ERROR_ARG,
- "invalid channel name");
+ r.Error(ACK_ERROR_ARG, "invalid channel name");
return CommandResult::ERROR;
case Client::SubscribeResult::ALREADY:
- command_error(client, ACK_ERROR_EXIST,
- "already subscribed to this channel");
+ r.Error(ACK_ERROR_EXIST, "already subscribed to this channel");
return CommandResult::ERROR;
case Client::SubscribeResult::FULL:
- command_error(client, ACK_ERROR_EXIST,
- "subscription list is full");
+ r.Error(ACK_ERROR_EXIST, "subscription list is full");
return CommandResult::ERROR;
}
@@ -66,14 +65,15 @@ handle_subscribe(Client &client, Request args)
CommandResult
handle_unsubscribe(Client &client, Request args)
{
+ Response r(client);
+
assert(args.size == 1);
const char *const channel_name = args[0];
if (client.Unsubscribe(channel_name))
return CommandResult::OK;
else {
- command_error(client, ACK_ERROR_NO_EXIST,
- "not subscribed to this channel");
+ r.Error(ACK_ERROR_NO_EXIST, "not subscribed to this channel");
return CommandResult::ERROR;
}
}
@@ -88,8 +88,9 @@ handle_channels(Client &client, gcc_unused Request args)
channels.insert(c.subscriptions.begin(),
c.subscriptions.end());
+ Response r(client);
for (const auto &channel : channels)
- client_printf(client, "channel: %s\n", channel.c_str());
+ r.Format("channel: %s\n", channel.c_str());
return CommandResult::OK;
}
@@ -100,11 +101,12 @@ handle_read_messages(Client &client,
{
assert(args.IsEmpty());
+ Response r(client);
while (!client.messages.empty()) {
const ClientMessage &msg = client.messages.front();
- client_printf(client, "channel: %s\nmessage: %s\n",
- msg.GetChannel(), msg.GetMessage());
+ r.Format("channel: %s\nmessage: %s\n",
+ msg.GetChannel(), msg.GetMessage());
client.messages.pop_front();
}
@@ -119,9 +121,9 @@ handle_send_message(Client &client, Request args)
const char *const channel_name = args[0];
const char *const message_text = args[1];
+ Response r(client);
if (!client_message_valid_channel_name(channel_name)) {
- command_error(client, ACK_ERROR_ARG,
- "invalid channel name");
+ r.Error(ACK_ERROR_ARG, "invalid channel name");
return CommandResult::ERROR;
}
@@ -134,8 +136,8 @@ handle_send_message(Client &client, Request args)
if (sent)
return CommandResult::OK;
else {
- command_error(client, ACK_ERROR_NO_EXIST,
- "nobody is subscribed to this channel");
+ r.Error(ACK_ERROR_NO_EXIST,
+ "nobody is subscribed to this channel");
return CommandResult::ERROR;
}
}
diff --git a/src/command/NeighborCommands.cxx b/src/command/NeighborCommands.cxx
index 10dbe3074..d1b2ec7c7 100644
--- a/src/command/NeighborCommands.cxx
+++ b/src/command/NeighborCommands.cxx
@@ -21,9 +21,9 @@
#include "NeighborCommands.hxx"
#include "Request.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Instance.hxx"
#include "Partition.hxx"
-#include "protocol/Result.hxx"
#include "neighbor/Glue.hxx"
#include "neighbor/Info.hxx"
#include "util/ConstBuffer.hxx"
@@ -42,19 +42,19 @@ neighbor_commands_available(const Instance &instance)
CommandResult
handle_listneighbors(Client &client, gcc_unused Request args)
{
+ Response r(client);
+
const NeighborGlue *const neighbors =
client.partition.instance.neighbors;
if (neighbors == nullptr) {
- command_error(client, ACK_ERROR_UNKNOWN,
- "No neighbor plugin configured");
+ r.Error(ACK_ERROR_UNKNOWN, "No neighbor plugin configured");
return CommandResult::ERROR;
}
for (const auto &i : neighbors->GetList())
- client_printf(client,
- "neighbor: %s\n"
- "name: %s\n",
- i.uri.c_str(),
- i.display_name.c_str());
+ r.Format("neighbor: %s\n"
+ "name: %s\n",
+ i.uri.c_str(),
+ i.display_name.c_str());
return CommandResult::OK;
}
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index 2e20d8dd5..c1346ca44 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
@@ -32,7 +32,6 @@
#include "tag/TagHandler.hxx"
#include "TimePrint.hxx"
#include "decoder/DecoderPrint.hxx"
-#include "protocol/Result.hxx"
#include "ls.hxx"
#include "mixer/Volume.hxx"
#include "util/UriUtil.hxx"
@@ -44,6 +43,7 @@
#include "PlaylistFile.hxx"
#include "db/PlaylistVector.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Idle.hxx"
@@ -58,36 +58,39 @@
#include <string.h>
static void
-print_spl_list(Client &client, const PlaylistVector &list)
+print_spl_list(Response &r, const PlaylistVector &list)
{
for (const auto &i : list) {
- client_printf(client, "playlist: %s\n", i.name.c_str());
+ r.Format("playlist: %s\n", i.name.c_str());
if (i.mtime > 0)
- time_print(client, "Last-Modified", i.mtime);
+ time_print(r, "Last-Modified", i.mtime);
}
}
CommandResult
handle_urlhandlers(Client &client, gcc_unused Request args)
{
+ Response r(client);
if (client.IsLocal())
- client_puts(client, "handler: file://\n");
- print_supported_uri_schemes(client);
+ r.Format("handler: file://\n");
+ print_supported_uri_schemes(r);
return CommandResult::OK;
}
CommandResult
handle_decoders(Client &client, gcc_unused Request args)
{
- decoder_list_print(client);
+ Response r(client);
+ decoder_list_print(r);
return CommandResult::OK;
}
CommandResult
handle_tagtypes(Client &client, gcc_unused Request args)
{
- tag_print_types(client);
+ Response r(client);
+ tag_print_types(r);
return CommandResult::OK;
}
@@ -106,14 +109,16 @@ handle_close(gcc_unused Client &client, gcc_unused Request args)
static void
print_tag(TagType type, const char *value, void *ctx)
{
- Client &client = *(Client *)ctx;
+ auto &r = *(Response *)ctx;
- tag_print(client, type, value);
+ tag_print(r, type, value);
}
CommandResult
handle_listfiles(Client &client, Request args)
{
+ Response r(client);
+
/* default is root directory */
const auto uri = args.GetOptional(0, "");
@@ -124,7 +129,7 @@ handle_listfiles(Client &client, Request args)
#ifdef ENABLE_DATABASE
if (uri_has_scheme(uri))
/* use storage plugin to list remote directory */
- return handle_listfiles_storage(client, uri);
+ return handle_listfiles_storage(r, uri);
/* must be a path relative to the configured
music_directory */
@@ -132,14 +137,14 @@ handle_listfiles(Client &client, Request args)
if (client.partition.instance.storage != nullptr)
/* if we have a storage instance, obtain a list of
files from it */
- return handle_listfiles_storage(client,
+ return handle_listfiles_storage(r,
*client.partition.instance.storage,
uri);
/* fall back to entries from database if we have no storage */
return handle_listfiles_db(client, uri);
#else
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
#endif
}
@@ -156,42 +161,40 @@ handle_lsinfo(Client &client, Request args)
/* default is root directory */
const auto uri = args.GetOptional(0, "");
+ Response r(client);
+
if (memcmp(uri, "file:///", 8) == 0) {
/* print information about an arbitrary local file */
const char *path_utf8 = uri + 7;
const auto path_fs = AllocatedPath::FromUTF8(path_utf8);
if (path_fs.IsNull()) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "unsupported file name");
+ r.Error(ACK_ERROR_NO_EXIST, "unsupported file name");
return CommandResult::ERROR;
}
Error error;
if (!client.AllowFile(path_fs, error))
- return print_error(client, error);
+ return print_error(r, error);
DetachedSong song(path_utf8);
if (!song.Update()) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "No such file");
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
return CommandResult::ERROR;
}
- song_print_info(client, song);
+ song_print_info(r, client.partition, song);
return CommandResult::OK;
}
if (uri_has_scheme(uri)) {
if (!uri_supported_scheme(uri)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "unsupported URI scheme");
+ r.Error(ACK_ERROR_NO_EXIST, "unsupported URI scheme");
return CommandResult::ERROR;
}
- if (!tag_stream_scan(uri, print_tag_handler, &client)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "No such file");
+ if (!tag_stream_scan(uri, print_tag_handler, &r)) {
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
return CommandResult::ERROR;
}
@@ -207,10 +210,10 @@ handle_lsinfo(Client &client, Request args)
if (isRootDirectory(uri)) {
Error error;
const auto &list = ListPlaylistFiles(error);
- print_spl_list(client, list);
+ print_spl_list(r, list);
} else {
#ifndef ENABLE_DATABASE
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
#endif
}
@@ -224,13 +227,14 @@ static CommandResult
handle_update(Client &client, UpdateService &update,
const char *uri_utf8, bool discard)
{
+ Response r(client);
+
unsigned ret = update.Enqueue(uri_utf8, discard);
if (ret > 0) {
- client_printf(client, "updating_db: %i\n", ret);
+ r.Format("updating_db: %i\n", ret);
return CommandResult::OK;
} else {
- command_error(client, ACK_ERROR_UPDATE_ALREADY,
- "already updating");
+ r.Error(ACK_ERROR_UPDATE_ALREADY, "already updating");
return CommandResult::ERROR;
}
}
@@ -239,17 +243,19 @@ static CommandResult
handle_update(Client &client, Database &db,
const char *uri_utf8, bool discard)
{
+ Response r(client);
+
Error error;
unsigned id = db.Update(uri_utf8, discard, error);
if (id > 0) {
- client_printf(client, "updating_db: %i\n", id);
+ r.Format("updating_db: %i\n", id);
return CommandResult::OK;
} else if (error.IsDefined()) {
- return print_error(client, error);
+ return print_error(r, error);
} else {
/* Database::Update() has returned 0 without setting
the Error: the method is not implemented */
- command_error(client, ACK_ERROR_NO_EXIST, "Not implemented");
+ r.Error(ACK_ERROR_NO_EXIST, "Not implemented");
return CommandResult::ERROR;
}
}
@@ -259,6 +265,8 @@ handle_update(Client &client, Database &db,
static CommandResult
handle_update(Client &client, Request args, bool discard)
{
+ Response r(client);
+
#ifdef ENABLE_DATABASE
const char *path = "";
@@ -270,8 +278,7 @@ handle_update(Client &client, Request args, bool discard)
/* backwards compatibility with MPD 0.15 */
path = "";
else if (!uri_safe_local(path)) {
- command_error(client, ACK_ERROR_ARG,
- "Malformed path");
+ r.Error(ACK_ERROR_ARG, "Malformed path");
return CommandResult::ERROR;
}
}
@@ -288,7 +295,7 @@ handle_update(Client &client, Request args, bool discard)
(void)discard;
#endif
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
}
@@ -307,13 +314,14 @@ handle_rescan(Client &client, gcc_unused Request args)
CommandResult
handle_setvol(Client &client, Request args)
{
+ Response r(client);
+
unsigned level;
- if (!args.Parse(0, level, client, 100))
+ if (!args.Parse(0, level, r, 100))
return CommandResult::ERROR;
if (!volume_level_change(client.partition.outputs, level)) {
- command_error(client, ACK_ERROR_SYSTEM,
- "problems setting volume");
+ r.Error(ACK_ERROR_SYSTEM, "problems setting volume");
return CommandResult::ERROR;
}
@@ -323,13 +331,15 @@ handle_setvol(Client &client, Request args)
CommandResult
handle_volume(Client &client, Request args)
{
+ Response r(client);
+
int relative;
- if (!args.Parse(0, relative, client, -100, 100))
+ if (!args.Parse(0, relative, r, -100, 100))
return CommandResult::ERROR;
const int old_volume = volume_level_get(client.partition.outputs);
if (old_volume < 0) {
- command_error(client, ACK_ERROR_SYSTEM, "No mixer");
+ r.Error(ACK_ERROR_SYSTEM, "No mixer");
return CommandResult::ERROR;
}
@@ -341,8 +351,7 @@ handle_volume(Client &client, Request args)
if (new_volume != old_volume &&
!volume_level_change(client.partition.outputs, new_volume)) {
- command_error(client, ACK_ERROR_SYSTEM,
- "problems setting volume");
+ r.Error(ACK_ERROR_SYSTEM, "problems setting volume");
return CommandResult::ERROR;
}
@@ -352,7 +361,8 @@ handle_volume(Client &client, Request args)
CommandResult
handle_stats(Client &client, gcc_unused Request args)
{
- stats_print(client);
+ Response r(client);
+ stats_print(r, client.partition);
return CommandResult::OK;
}
@@ -365,10 +375,11 @@ handle_ping(gcc_unused Client &client, gcc_unused Request args)
CommandResult
handle_password(Client &client, Request args)
{
- unsigned permission = 0;
+ Response r(client);
+ unsigned permission = 0;
if (getPermissionFromPassword(args.front(), &permission) < 0) {
- command_error(client, ACK_ERROR_PASSWORD, "incorrect password");
+ r.Error(ACK_ERROR_PASSWORD, "incorrect password");
return CommandResult::ERROR;
}
@@ -380,9 +391,11 @@ handle_password(Client &client, Request args)
CommandResult
handle_config(Client &client, gcc_unused Request args)
{
+ Response r(client);
+
if (!client.IsLocal()) {
- command_error(client, ACK_ERROR_PERMISSION,
- "Command only permitted to local clients");
+ r.Error(ACK_ERROR_PERMISSION,
+ "Command only permitted to local clients");
return CommandResult::ERROR;
}
@@ -390,7 +403,7 @@ handle_config(Client &client, gcc_unused Request args)
const Storage *storage = client.GetStorage();
if (storage != nullptr) {
const auto path = storage->MapUTF8("");
- client_printf(client, "music_directory: %s\n", path.c_str());
+ r.Format("music_directory: %s\n", path.c_str());
}
#endif
@@ -400,14 +413,14 @@ handle_config(Client &client, gcc_unused Request args)
CommandResult
handle_idle(Client &client, Request args)
{
- unsigned flags = 0;
+ Response r(client);
+ unsigned flags = 0;
for (const char *i : args) {
unsigned event = idle_parse_name(i);
if (event == 0) {
- command_error(client, ACK_ERROR_ARG,
- "Unrecognized idle event: %s",
- i);
+ r.FormatError(ACK_ERROR_ARG,
+ "Unrecognized idle event: %s", i);
return CommandResult::ERROR;
}
diff --git a/src/command/OutputCommands.cxx b/src/command/OutputCommands.cxx
index 39602aba8..472516860 100644
--- a/src/command/OutputCommands.cxx
+++ b/src/command/OutputCommands.cxx
@@ -22,23 +22,23 @@
#include "Request.hxx"
#include "output/OutputPrint.hxx"
#include "output/OutputCommand.hxx"
-#include "protocol/Result.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Partition.hxx"
#include "util/ConstBuffer.hxx"
CommandResult
handle_enableoutput(Client &client, Request args)
{
- assert(args.size == 1);
+ Response r(client);
+ assert(args.size == 1);
unsigned device;
- if (!args.Parse(0, device, client))
+ if (!args.Parse(0, device, r))
return CommandResult::ERROR;
if (!audio_output_enable_index(client.partition.outputs, device)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "No such audio output");
+ r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}
@@ -48,15 +48,15 @@ handle_enableoutput(Client &client, Request args)
CommandResult
handle_disableoutput(Client &client, Request args)
{
- assert(args.size == 1);
+ Response r(client);
+ assert(args.size == 1);
unsigned device;
- if (!args.Parse(0, device, client))
+ if (!args.Parse(0, device, r))
return CommandResult::ERROR;
if (!audio_output_disable_index(client.partition.outputs, device)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "No such audio output");
+ r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}
@@ -66,15 +66,15 @@ handle_disableoutput(Client &client, Request args)
CommandResult
handle_toggleoutput(Client &client, Request args)
{
- assert(args.size == 1);
+ Response r(client);
+ assert(args.size == 1);
unsigned device;
- if (!args.Parse(0, device, client))
+ if (!args.Parse(0, device, r))
return CommandResult::ERROR;
if (!audio_output_toggle_index(client.partition.outputs, device)) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "No such audio output");
+ r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}
@@ -86,7 +86,8 @@ handle_devices(Client &client, gcc_unused Request args)
{
assert(args.IsEmpty());
- printAudioDevices(client, client.partition.outputs);
+ Response r(client);
+ printAudioDevices(r, client.partition.outputs);
return CommandResult::OK;
}
diff --git a/src/command/PlayerCommands.cxx b/src/command/PlayerCommands.cxx
index e0c0f61a8..3e58cecb1 100644
--- a/src/command/PlayerCommands.cxx
+++ b/src/command/PlayerCommands.cxx
@@ -24,10 +24,10 @@
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "mixer/Volume.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
-#include "protocol/Result.hxx"
#include "AudioFormat.hxx"
#include "ReplayGainConfig.hxx"
#include "util/ConstBuffer.hxx"
@@ -59,23 +59,27 @@
CommandResult
handle_play(Client &client, Request args)
{
+ Response r(client);
+
int song = -1;
- if (!args.ParseOptional(0, song, client))
+ if (!args.ParseOptional(0, song, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayPosition(song);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_playid(Client &client, Request args)
{
+ Response r(client);
+
int id = -1;
- if (!args.ParseOptional(0, id, client))
+ if (!args.ParseOptional(0, id, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayId(id);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
@@ -88,16 +92,19 @@ handle_stop(Client &client, gcc_unused Request args)
CommandResult
handle_currentsong(Client &client, gcc_unused Request args)
{
- playlist_print_current(client, client.playlist);
+ Response r(client);
+ playlist_print_current(r, client.partition, client.playlist);
return CommandResult::OK;
}
CommandResult
handle_pause(Client &client, Request args)
{
+ Response r(client);
+
if (!args.IsEmpty()) {
bool pause_flag;
- if (!args.Parse(0, pause_flag, client))
+ if (!args.Parse(0, pause_flag, r))
return CommandResult::ERROR;
client.player_control.SetPause(pause_flag);
@@ -127,68 +134,64 @@ handle_status(Client &client, gcc_unused Request args)
break;
}
+ Response r(client);
+
const playlist &playlist = client.playlist;
- client_printf(client,
- "volume: %i\n"
- COMMAND_STATUS_REPEAT ": %i\n"
- COMMAND_STATUS_RANDOM ": %i\n"
- COMMAND_STATUS_SINGLE ": %i\n"
- COMMAND_STATUS_CONSUME ": %i\n"
- COMMAND_STATUS_PLAYLIST ": %li\n"
- COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n"
- COMMAND_STATUS_MIXRAMPDB ": %f\n"
- COMMAND_STATUS_STATE ": %s\n",
- volume_level_get(client.partition.outputs),
- playlist.GetRepeat(),
- playlist.GetRandom(),
- playlist.GetSingle(),
- playlist.GetConsume(),
- (unsigned long)playlist.GetVersion(),
- playlist.GetLength(),
- client.player_control.GetMixRampDb(),
- state);
+ r.Format("volume: %i\n"
+ COMMAND_STATUS_REPEAT ": %i\n"
+ COMMAND_STATUS_RANDOM ": %i\n"
+ COMMAND_STATUS_SINGLE ": %i\n"
+ COMMAND_STATUS_CONSUME ": %i\n"
+ COMMAND_STATUS_PLAYLIST ": %li\n"
+ COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n"
+ COMMAND_STATUS_MIXRAMPDB ": %f\n"
+ COMMAND_STATUS_STATE ": %s\n",
+ volume_level_get(client.partition.outputs),
+ playlist.GetRepeat(),
+ playlist.GetRandom(),
+ playlist.GetSingle(),
+ playlist.GetConsume(),
+ (unsigned long)playlist.GetVersion(),
+ playlist.GetLength(),
+ client.player_control.GetMixRampDb(),
+ state);
if (client.player_control.GetCrossFade() > 0)
- client_printf(client,
- COMMAND_STATUS_CROSSFADE ": %i\n",
- int(client.player_control.GetCrossFade() + 0.5));
+ r.Format(COMMAND_STATUS_CROSSFADE ": %i\n",
+ int(client.player_control.GetCrossFade() + 0.5));
if (client.player_control.GetMixRampDelay() > 0)
- client_printf(client,
- COMMAND_STATUS_MIXRAMPDELAY ": %f\n",
- client.player_control.GetMixRampDelay());
+ r.Format(COMMAND_STATUS_MIXRAMPDELAY ": %f\n",
+ client.player_control.GetMixRampDelay());
song = playlist.GetCurrentPosition();
if (song >= 0) {
- client_printf(client,
- COMMAND_STATUS_SONG ": %i\n"
- COMMAND_STATUS_SONGID ": %u\n",
- song, playlist.PositionToId(song));
+ r.Format(COMMAND_STATUS_SONG ": %i\n"
+ COMMAND_STATUS_SONGID ": %u\n",
+ song, playlist.PositionToId(song));
}
if (player_status.state != PlayerState::STOP) {
- client_printf(client,
- COMMAND_STATUS_TIME ": %i:%i\n"
- "elapsed: %1.3f\n"
- COMMAND_STATUS_BITRATE ": %u\n",
- player_status.elapsed_time.RoundS(),
- player_status.total_time.IsNegative()
- ? 0u
- : unsigned(player_status.total_time.RoundS()),
- player_status.elapsed_time.ToDoubleS(),
- player_status.bit_rate);
+ r.Format(COMMAND_STATUS_TIME ": %i:%i\n"
+ "elapsed: %1.3f\n"
+ COMMAND_STATUS_BITRATE ": %u\n",
+ player_status.elapsed_time.RoundS(),
+ player_status.total_time.IsNegative()
+ ? 0u
+ : unsigned(player_status.total_time.RoundS()),
+ player_status.elapsed_time.ToDoubleS(),
+ player_status.bit_rate);
if (!player_status.total_time.IsNegative())
- client_printf(client, "duration: %1.3f\n",
- player_status.total_time.ToDoubleS());
+ r.Format("duration: %1.3f\n",
+ player_status.total_time.ToDoubleS());
if (player_status.audio_format.IsDefined()) {
struct audio_format_string af_string;
- client_printf(client,
- COMMAND_STATUS_AUDIO ": %s\n",
- audio_format_to_string(player_status.audio_format,
- &af_string));
+ r.Format(COMMAND_STATUS_AUDIO ": %s\n",
+ audio_format_to_string(player_status.audio_format,
+ &af_string));
}
}
@@ -198,25 +201,21 @@ handle_status(Client &client, gcc_unused Request args)
? update_service->GetId()
: 0;
if (updateJobId != 0) {
- client_printf(client,
- COMMAND_STATUS_UPDATING_DB ": %i\n",
- updateJobId);
+ r.Format(COMMAND_STATUS_UPDATING_DB ": %i\n",
+ updateJobId);
}
#endif
Error error = client.player_control.LockGetError();
if (error.IsDefined())
- client_printf(client,
- COMMAND_STATUS_ERROR ": %s\n",
- error.GetMessage());
+ r.Format(COMMAND_STATUS_ERROR ": %s\n",
+ error.GetMessage());
song = playlist.GetNextPosition();
- if (song >= 0) {
- client_printf(client,
- COMMAND_STATUS_NEXTSONG ": %i\n"
- COMMAND_STATUS_NEXTSONGID ": %u\n",
- song, playlist.PositionToId(song));
- }
+ if (song >= 0)
+ r.Format(COMMAND_STATUS_NEXTSONG ": %i\n"
+ COMMAND_STATUS_NEXTSONGID ": %u\n",
+ song, playlist.PositionToId(song));
return CommandResult::OK;
}
@@ -247,8 +246,10 @@ handle_previous(Client &client, gcc_unused Request args)
CommandResult
handle_repeat(Client &client, Request args)
{
+ Response r(client);
+
bool status;
- if (!args.Parse(0, status, client))
+ if (!args.Parse(0, status, r))
return CommandResult::ERROR;
client.partition.SetRepeat(status);
@@ -258,8 +259,10 @@ handle_repeat(Client &client, Request args)
CommandResult
handle_single(Client &client, Request args)
{
+ Response r(client);
+
bool status;
- if (!args.Parse(0, status, client))
+ if (!args.Parse(0, status, r))
return CommandResult::ERROR;
client.partition.SetSingle(status);
@@ -269,8 +272,10 @@ handle_single(Client &client, Request args)
CommandResult
handle_consume(Client &client, Request args)
{
+ Response r(client);
+
bool status;
- if (!args.Parse(0, status, client))
+ if (!args.Parse(0, status, r))
return CommandResult::ERROR;
client.partition.SetConsume(status);
@@ -280,8 +285,10 @@ handle_consume(Client &client, Request args)
CommandResult
handle_random(Client &client, Request args)
{
+ Response r(client);
+
bool status;
- if (!args.Parse(0, status, client))
+ if (!args.Parse(0, status, r))
return CommandResult::ERROR;
client.partition.SetRandom(status);
@@ -299,53 +306,58 @@ handle_clearerror(gcc_unused Client &client, gcc_unused Request args)
CommandResult
handle_seek(Client &client, Request args)
{
+ Response r(client);
+
unsigned song;
SongTime seek_time;
-
- if (!args.Parse(0, song, client))
- return CommandResult::ERROR;
- if (!args.Parse(1, seek_time, client))
+ if (!args.Parse(0, song, r) || !args.Parse(1, seek_time, r))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.SeekSongPosition(song, seek_time);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_seekid(Client &client, Request args)
{
+ Response r(client);
+
unsigned id;
SongTime seek_time;
- if (!args.Parse(0, id, client))
+ if (!args.Parse(0, id, r))
return CommandResult::ERROR;
- if (!args.Parse(1, seek_time, client))
+ if (!args.Parse(1, seek_time, r))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.SeekSongId(id, seek_time);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_seekcur(Client &client, Request args)
{
+ Response r(client);
+
const char *p = args.front();
bool relative = *p == '+' || *p == '-';
SignedSongTime seek_time;
- if (!ParseCommandArg(client, seek_time, p))
+ if (!ParseCommandArg(r, seek_time, p))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.SeekCurrent(seek_time, relative);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_crossfade(Client &client, Request args)
{
+ Response r(client);
+
unsigned xfade_time;
- if (!args.Parse(0, xfade_time, client))
+ if (!args.Parse(0, xfade_time, r))
return CommandResult::ERROR;
client.player_control.SetCrossFade(xfade_time);
@@ -355,8 +367,10 @@ handle_crossfade(Client &client, Request args)
CommandResult
handle_mixrampdb(Client &client, Request args)
{
+ Response r(client);
+
float db;
- if (!args.Parse(0, db, client))
+ if (!args.Parse(0, db, r))
return CommandResult::ERROR;
client.player_control.SetMixRampDb(db);
@@ -366,8 +380,10 @@ handle_mixrampdb(Client &client, Request args)
CommandResult
handle_mixrampdelay(Client &client, Request args)
{
+ Response r(client);
+
float delay_secs;
- if (!args.Parse(0, delay_secs, client))
+ if (!args.Parse(0, delay_secs, r))
return CommandResult::ERROR;
client.player_control.SetMixRampDelay(delay_secs);
@@ -378,9 +394,10 @@ handle_mixrampdelay(Client &client, Request args)
CommandResult
handle_replay_gain_mode(Client &client, Request args)
{
+ Response r(client);
+
if (!replay_gain_set_mode_string(args.front())) {
- command_error(client, ACK_ERROR_ARG,
- "Unrecognized replay gain mode");
+ r.Error(ACK_ERROR_ARG, "Unrecognized replay gain mode");
return CommandResult::ERROR;
}
@@ -391,7 +408,7 @@ handle_replay_gain_mode(Client &client, Request args)
CommandResult
handle_replay_gain_status(Client &client, gcc_unused Request args)
{
- client_printf(client, "replay_gain_mode: %s\n",
- replay_gain_get_mode_string());
+ Response r(client);
+ r.Format("replay_gain_mode: %s\n", replay_gain_get_mode_string());
return CommandResult::OK;
}
diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx
index 0122cecbd..1e075e088 100644
--- a/src/command/PlaylistCommands.cxx
+++ b/src/command/PlaylistCommands.cxx
@@ -33,7 +33,7 @@
#include "queue/Playlist.hxx"
#include "TimePrint.hxx"
#include "client/Client.hxx"
-#include "protocol/Result.hxx"
+#include "client/Response.hxx"
#include "ls.hxx"
#include "Mapper.hxx"
#include "fs/AllocatedPath.hxx"
@@ -48,30 +48,33 @@ playlist_commands_available()
}
static void
-print_spl_list(Client &client, const PlaylistVector &list)
+print_spl_list(Response &r, const PlaylistVector &list)
{
for (const auto &i : list) {
- client_printf(client, "playlist: %s\n", i.name.c_str());
+ r.Format("playlist: %s\n", i.name.c_str());
if (i.mtime > 0)
- time_print(client, "Last-Modified", i.mtime);
+ time_print(r, "Last-Modified", i.mtime);
}
}
CommandResult
handle_save(Client &client, Request args)
{
+ Response r(client);
Error error;
return spl_save_playlist(args.front(), client.playlist, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_load(Client &client, Request args)
{
+ Response r(client);
+
RangeArg range = RangeArg::All();
- if (!args.ParseOptional(1, range, client))
+ if (!args.ParseOptional(1, range, r))
return CommandResult::ERROR;
const ScopeBulkEdit bulk_edit(client.partition);
@@ -82,7 +85,7 @@ handle_load(Client &client, Request args)
range.start, range.end,
client.playlist,
client.player_control, loader, error))
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -90,97 +93,114 @@ handle_load(Client &client, Request args)
CommandResult
handle_listplaylist(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args.front();
- if (playlist_file_print(client, name, false))
+ if (playlist_file_print(r, client.partition, SongLoader(client),
+ name, false))
return CommandResult::OK;
Error error;
- return spl_print(client, name, false, error)
+ return spl_print(r, client.partition, name, false, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_listplaylistinfo(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args.front();
- if (playlist_file_print(client, name, true))
+ if (playlist_file_print(r, client.partition, SongLoader(client),
+ name, true))
return CommandResult::OK;
Error error;
- return spl_print(client, name, true, error)
+ return spl_print(r, client.partition, name, true, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_rm(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args.front();
Error error;
return spl_delete(name, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_rename(Client &client, Request args)
{
+ Response r(client);
+
const char *const old_name = args[0];
const char *const new_name = args[1];
Error error;
return spl_rename(old_name, new_name, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_playlistdelete(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args[0];
unsigned from;
- if (!args.Parse(1, from, client))
+ if (!args.Parse(1, from, r))
return CommandResult::ERROR;
Error error;
return spl_remove_index(name, from, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_playlistmove(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args.front();
unsigned from, to;
- if (!args.Parse(1, from, client) ||
- !args.Parse(2, to, client))
+ if (!args.Parse(1, from, r) || !args.Parse(2, to, r))
return CommandResult::ERROR;
Error error;
return spl_move_index(name, from, to, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_playlistclear(Client &client, Request args)
{
+ Response r(client);
+
const char *const name = args.front();
Error error;
return spl_clear(name, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
}
CommandResult
handle_playlistadd(Client &client, Request args)
{
+ Response r(client);
+
const char *const playlist = args[0];
const char *const uri = args[1];
@@ -193,7 +213,7 @@ handle_playlistadd(Client &client, Request args)
#ifdef ENABLE_DATABASE
const Database *db = client.GetDatabase(error);
if (db == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
success = search_add_to_playlist(*db, *client.GetStorage(),
uri, playlist, nullptr,
@@ -204,22 +224,23 @@ handle_playlistadd(Client &client, Request args)
}
if (!success && !error.IsDefined()) {
- command_error(client, ACK_ERROR_NO_EXIST,
- "directory or file not found");
+ r.Error(ACK_ERROR_NO_EXIST, "directory or file not found");
return CommandResult::ERROR;
}
- return success ? CommandResult::OK : print_error(client, error);
+ return success ? CommandResult::OK : print_error(r, error);
}
CommandResult
handle_listplaylists(Client &client, gcc_unused Request args)
{
+ Response r(client);
+
Error error;
const auto list = ListPlaylistFiles(error);
if (list.empty() && error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- print_spl_list(client, list);
+ print_spl_list(r, list);
return CommandResult::OK;
}
diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx
index 1413a68c9..850631ded 100644
--- a/src/command/QueueCommands.cxx
+++ b/src/command/QueueCommands.cxx
@@ -28,9 +28,9 @@
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Partition.hxx"
#include "BulkEdit.hxx"
-#include "protocol/Result.hxx"
#include "ls.hxx"
#include "util/ConstBuffer.hxx"
#include "util/UriUtil.hxx"
@@ -56,6 +56,8 @@ translate_uri(const char *uri)
CommandResult
handle_add(Client &client, Request args)
{
+ Response r(client);
+
const char *uri = args.front();
if (memcmp(uri, "/", 2) == 0)
/* this URI is malformed, but some clients are buggy
@@ -72,7 +74,7 @@ handle_add(Client &client, Request args)
Error error;
unsigned id = client.partition.AppendURI(loader, uri, error);
if (id == 0)
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -84,9 +86,9 @@ handle_add(Client &client, Request args)
Error error;
return AddFromDatabase(client.partition, selection, error)
? CommandResult::OK
- : print_error(client, error);
+ : print_error(r, error);
#else
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
#endif
}
@@ -94,29 +96,31 @@ handle_add(Client &client, Request args)
CommandResult
handle_addid(Client &client, Request args)
{
+ Response r(client);
+
const char *const uri = translate_uri(args.front());
const SongLoader loader(client);
Error error;
unsigned added_id = client.partition.AppendURI(loader, uri, error);
if (added_id == 0)
- return print_error(client, error);
+ return print_error(r, error);
if (args.size == 2) {
unsigned to;
- if (!args.Parse(1, to, client))
+ if (!args.Parse(1, to, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.MoveId(added_id, to);
if (result != PlaylistResult::SUCCESS) {
CommandResult ret =
- print_playlist_result(client, result);
+ print_playlist_result(r, result);
client.partition.DeleteId(added_id);
return ret;
}
}
- client_printf(client, "Id: %u\n", added_id);
+ r.Format("Id: %u\n", added_id);
return CommandResult::OK;
}
@@ -154,13 +158,15 @@ parse_time_range(const char *p, SongTime &start_r, SongTime &end_r)
CommandResult
handle_rangeid(Client &client, Request args)
{
+ Response r(client);
+
unsigned id;
- if (!args.Parse(0, id, client))
+ if (!args.Parse(0, id, r))
return CommandResult::ERROR;
SongTime start, end;
if (!parse_time_range(args[1], start, end)) {
- command_error(client, ACK_ERROR_ARG, "Bad range");
+ r.Error(ACK_ERROR_ARG, "Bad range");
return CommandResult::ERROR;
}
@@ -168,7 +174,7 @@ handle_rangeid(Client &client, Request args)
if (!client.partition.playlist.SetSongIdRange(client.partition.pc,
id, start, end,
error))
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -176,37 +182,44 @@ handle_rangeid(Client &client, Request args)
CommandResult
handle_delete(Client &client, Request args)
{
+ Response r(client);
+
RangeArg range;
- if (!args.Parse(0, range, client))
+ if (!args.Parse(0, range, r))
return CommandResult::ERROR;
auto result = client.partition.DeleteRange(range.start, range.end);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_deleteid(Client &client, Request args)
{
+ Response r(client);
+
unsigned id;
- if (!args.Parse(0, id, client))
+ if (!args.Parse(0, id, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.DeleteId(id);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_playlist(Client &client, gcc_unused Request args)
{
- playlist_print_uris(client, client.playlist);
+ Response r(client);
+ playlist_print_uris(r, client.partition, client.playlist);
return CommandResult::OK;
}
CommandResult
handle_shuffle(gcc_unused Client &client, Request args)
{
+ Response r(client);
+
RangeArg range = RangeArg::All();
- if (!args.ParseOptional(0, range, client))
+ if (!args.ParseOptional(0, range, r))
return CommandResult::ERROR;
client.partition.Shuffle(range.start, range.end);
@@ -223,37 +236,42 @@ handle_clear(gcc_unused Client &client, gcc_unused Request args)
CommandResult
handle_plchanges(Client &client, Request args)
{
- uint32_t version;
+ Response r(client);
- if (!check_uint32(client, &version, args.front()))
+ uint32_t version;
+ if (!ParseCommandArg32(r, version, args.front()))
return CommandResult::ERROR;
- playlist_print_changes_info(client, client.playlist, version);
+ playlist_print_changes_info(r, client.partition,
+ client.playlist, version);
return CommandResult::OK;
}
CommandResult
handle_plchangesposid(Client &client, Request args)
{
- uint32_t version;
+ Response r(client);
- if (!check_uint32(client, &version, args.front()))
+ uint32_t version;
+ if (!ParseCommandArg32(r, version, args.front()))
return CommandResult::ERROR;
- playlist_print_changes_position(client, client.playlist, version);
+ playlist_print_changes_position(r, client.playlist, version);
return CommandResult::OK;
}
CommandResult
handle_playlistinfo(Client &client, Request args)
{
+ Response r(client);
+
RangeArg range = RangeArg::All();
- if (!args.ParseOptional(0, range, client))
+ if (!args.ParseOptional(0, range, r))
return CommandResult::ERROR;
- if (!playlist_print_info(client, client.playlist,
+ if (!playlist_print_info(r, client.partition, client.playlist,
range.start, range.end))
- return print_playlist_result(client,
+ return print_playlist_result(r,
PlaylistResult::BAD_RANGE);
return CommandResult::OK;
@@ -262,17 +280,19 @@ handle_playlistinfo(Client &client, Request args)
CommandResult
handle_playlistid(Client &client, Request args)
{
+ Response r(client);
+
if (!args.IsEmpty()) {
unsigned id;
- if (!args.Parse(0, id, client))
+ if (!args.Parse(0, id, r))
return CommandResult::ERROR;
- bool ret = playlist_print_id(client, client.playlist, id);
+ bool ret = playlist_print_id(r, client.partition,
+ client.playlist, id);
if (!ret)
- return print_playlist_result(client,
- PlaylistResult::NO_SUCH_SONG);
+ return print_playlist_result(r, PlaylistResult::NO_SUCH_SONG);
} else {
- playlist_print_info(client, client.playlist,
+ playlist_print_info(r, client.partition, client.playlist,
0, std::numeric_limits<unsigned>::max());
}
@@ -283,13 +303,15 @@ static CommandResult
handle_playlist_match(Client &client, Request args,
bool fold_case)
{
+ Response r(client);
+
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
- command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ r.Error(ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
- playlist_print_find(client, client.playlist, filter);
+ playlist_print_find(r, client.partition, client.playlist, filter);
return CommandResult::OK;
}
@@ -308,13 +330,15 @@ handle_playlistsearch(Client &client, Request args)
CommandResult
handle_prio(Client &client, Request args)
{
+ Response r(client);
+
unsigned priority;
- if (!args.ParseShift(0, priority, client, 0xff))
+ if (!args.ParseShift(0, priority, r, 0xff))
return CommandResult::ERROR;
for (const char *i : args) {
RangeArg range;
- if (!ParseCommandArg(client, range, i))
+ if (!ParseCommandArg(r, range, i))
return CommandResult::ERROR;
PlaylistResult result =
@@ -322,7 +346,7 @@ handle_prio(Client &client, Request args)
range.end,
priority);
if (result != PlaylistResult::SUCCESS)
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
return CommandResult::OK;
@@ -331,19 +355,21 @@ handle_prio(Client &client, Request args)
CommandResult
handle_prioid(Client &client, Request args)
{
+ Response r(client);
+
unsigned priority;
- if (!args.ParseShift(0, priority, client, 0xff))
+ if (!args.ParseShift(0, priority, r, 0xff))
return CommandResult::ERROR;
for (const char *i : args) {
unsigned song_id;
- if (!ParseCommandArg(client, song_id, i))
+ if (!ParseCommandArg(r, song_id, i))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.SetPriorityId(song_id, priority);
if (result != PlaylistResult::SUCCESS)
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
return CommandResult::OK;
@@ -352,52 +378,56 @@ handle_prioid(Client &client, Request args)
CommandResult
handle_move(Client &client, Request args)
{
+ Response r(client);
+
RangeArg range;
int to;
- if (!args.Parse(0, range, client) ||
- !args.Parse(1, to, client))
+ if (!args.Parse(0, range, r) || !args.Parse(1, to, r))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.MoveRange(range.start, range.end, to);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_moveid(Client &client, Request args)
{
+ Response r(client);
+
unsigned id;
int to;
- if (!args.Parse(0, id, client) ||
- !args.Parse(1, to, client))
+ if (!args.Parse(0, id, r) || !args.Parse(1, to, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.MoveId(id, to);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_swap(Client &client, Request args)
{
+ Response r(client);
+
unsigned song1, song2;
- if (!args.Parse(0, song1, client) ||
- !args.Parse(1, song2, client))
+ if (!args.Parse(0, song1, r) || !args.Parse(1, song2, r))
return CommandResult::ERROR;
PlaylistResult result =
client.partition.SwapPositions(song1, song2);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
CommandResult
handle_swapid(Client &client, Request args)
{
+ Response r(client);
+
unsigned id1, id2;
- if (!args.Parse(0, id1, client) ||
- !args.Parse(1, id2, client))
+ if (!args.Parse(0, id1, r) || !args.Parse(1, id2, r))
return CommandResult::ERROR;
PlaylistResult result = client.partition.SwapIds(id1, id2);
- return print_playlist_result(client, result);
+ return print_playlist_result(r, result);
}
diff --git a/src/command/Request.hxx b/src/command/Request.hxx
index 38b3c584c..1616b7045 100644
--- a/src/command/Request.hxx
+++ b/src/command/Request.hxx
@@ -28,7 +28,7 @@
#include <assert.h>
-class Client;
+class Response;
class Request : public ConstBuffer<const char *> {
typedef ConstBuffer<const char *> Base;
@@ -45,26 +45,26 @@ public:
}
template<typename T, typename... Args>
- bool Parse(unsigned idx, T &value_r, Client &client,
+ bool Parse(unsigned idx, T &value_r, Response &r,
Args&&... args) {
assert(idx < size);
- return ParseCommandArg(client, value_r, data[idx],
+ return ParseCommandArg(r, value_r, data[idx],
std::forward<Args>(args)...);
}
template<typename T, typename... Args>
- bool ParseOptional(unsigned idx, T &value_r, Client &client,
+ bool ParseOptional(unsigned idx, T &value_r, Response &r,
Args&&... args) {
return idx >= size ||
- Parse(idx, value_r, client,
+ Parse(idx, value_r, r,
std::forward<Args>(args)...);
}
template<typename T, typename... Args>
- bool ParseShift(unsigned idx, T &value_r, Client &client,
+ bool ParseShift(unsigned idx, T &value_r, Response &r,
Args&&... args) {
- bool success = Parse(idx, value_r, client,
+ bool success = Parse(idx, value_r, r,
std::forward<Args>(args)...);
shift();
return success;
diff --git a/src/command/StickerCommands.cxx b/src/command/StickerCommands.cxx
index a28408547..25d354b2e 100644
--- a/src/command/StickerCommands.cxx
+++ b/src/command/StickerCommands.cxx
@@ -27,8 +27,8 @@
#include "sticker/StickerPrint.hxx"
#include "sticker/StickerDatabase.hxx"
#include "CommandError.hxx"
-#include "protocol/Result.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "util/Error.hxx"
@@ -37,7 +37,8 @@
#include <string.h>
struct sticker_song_find_data {
- Client &client;
+ Response &r;
+ Partition &partition;
const char *name;
};
@@ -48,17 +49,17 @@ sticker_song_find_print_cb(const LightSong &song, const char *value,
struct sticker_song_find_data *data =
(struct sticker_song_find_data *)user_data;
- song_print_uri(data->client, song);
- sticker_print_value(data->client, data->name, value);
+ song_print_uri(data->r, data->partition, song);
+ sticker_print_value(data->r, data->name, value);
}
static CommandResult
-handle_sticker_song(Client &client, Request args)
+handle_sticker_song(Response &r, Partition &partition, Request args)
{
Error error;
- const Database *db = client.GetDatabase(error);
+ const Database *db = partition.GetDatabase(error);
if (db == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
const char *const cmd = args.front();
@@ -66,53 +67,52 @@ handle_sticker_song(Client &client, Request args)
if (args.size == 4 && strcmp(cmd, "get") == 0) {
const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
const auto value = sticker_song_get_value(*song, args[3],
error);
db->ReturnSong(song);
if (value.empty()) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_NO_EXIST,
- "no such sticker");
+ r.Error(ACK_ERROR_NO_EXIST, "no such sticker");
return CommandResult::ERROR;
}
- sticker_print_value(client, args[3], value.c_str());
+ sticker_print_value(r, args[3], value.c_str());
return CommandResult::OK;
/* list song song_id */
} else if (args.size == 3 && strcmp(cmd, "list") == 0) {
const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
Sticker *sticker = sticker_song_get(*song, error);
db->ReturnSong(song);
if (sticker) {
- sticker_print(client, *sticker);
+ sticker_print(r, *sticker);
sticker_free(sticker);
} else if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
/* set song song_id id key */
} else if (args.size == 5 && strcmp(cmd, "set") == 0) {
const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
bool ret = sticker_song_set_value(*song, args[3], args[4],
error);
db->ReturnSong(song);
if (!ret) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_SYSTEM,
- "failed to set sticker value");
+ r.Error(ACK_ERROR_SYSTEM,
+ "failed to set sticker value");
return CommandResult::ERROR;
}
@@ -122,7 +122,7 @@ handle_sticker_song(Client &client, Request args)
strcmp(cmd, "delete") == 0) {
const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
- return print_error(client, error);
+ return print_error(r, error);
bool ret = args.size == 3
? sticker_song_delete(*song, error)
@@ -130,10 +130,9 @@ handle_sticker_song(Client &client, Request args)
db->ReturnSong(song);
if (!ret) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_SYSTEM,
- "no such sticker");
+ r.Error(ACK_ERROR_SYSTEM, "no such sticker");
return CommandResult::ERROR;
}
@@ -161,14 +160,14 @@ handle_sticker_song(Client &client, Request args)
else if (strcmp(op_s, ">") == 0)
op = StickerOperator::GREATER_THAN;
else {
- command_error(client, ACK_ERROR_ARG,
- "bad operator");
+ r.Error(ACK_ERROR_ARG, "bad operator");
return CommandResult::ERROR;
}
}
struct sticker_song_find_data data = {
- client,
+ r,
+ partition,
args[3],
};
@@ -177,16 +176,16 @@ handle_sticker_song(Client &client, Request args)
sticker_song_find_print_cb, &data,
error)) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_SYSTEM,
- "failed to set search sticker database");
+ r.Error(ACK_ERROR_SYSTEM,
+ "failed to set search sticker database");
return CommandResult::ERROR;
}
return CommandResult::OK;
} else {
- command_error(client, ACK_ERROR_ARG, "bad request");
+ r.Error(ACK_ERROR_ARG, "bad request");
return CommandResult::ERROR;
}
}
@@ -194,19 +193,19 @@ handle_sticker_song(Client &client, Request args)
CommandResult
handle_sticker(Client &client, Request args)
{
+ Response r(client);
+
assert(args.size >= 3);
if (!sticker_enabled()) {
- command_error(client, ACK_ERROR_UNKNOWN,
- "sticker database is disabled");
+ r.Error(ACK_ERROR_UNKNOWN, "sticker database is disabled");
return CommandResult::ERROR;
}
if (strcmp(args[1], "song") == 0)
- return handle_sticker_song(client, args);
+ return handle_sticker_song(r, client.partition, args);
else {
- command_error(client, ACK_ERROR_ARG,
- "unknown sticker domain");
+ r.Error(ACK_ERROR_ARG, "unknown sticker domain");
return CommandResult::ERROR;
}
}
diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx
index 3f1e5f321..edf2f60b8 100644
--- a/src/command/StorageCommands.cxx
+++ b/src/command/StorageCommands.cxx
@@ -23,12 +23,12 @@
#include "StorageCommands.hxx"
#include "Request.hxx"
#include "CommandError.hxx"
-#include "protocol/Result.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "fs/Traits.hxx"
#include "client/Client.hxx"
+#include "client/Response.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "storage/Registry.hxx"
@@ -57,7 +57,7 @@ skip_path(const char *name_utf8)
#endif
static bool
-handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
+handle_listfiles_storage(Response &r, StorageDirectoryReader &reader,
Error &error)
{
const char *name_utf8;
@@ -75,19 +75,19 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
continue;
case StorageFileInfo::Type::REGULAR:
- client_printf(client, "file: %s\n"
- "size: %" PRIu64 "\n",
- name_utf8,
- info.size);
+ r.Format("file: %s\n"
+ "size: %" PRIu64 "\n",
+ name_utf8,
+ info.size);
break;
case StorageFileInfo::Type::DIRECTORY:
- client_printf(client, "directory: %s\n", name_utf8);
+ r.Format("directory: %s\n", name_utf8);
break;
}
if (info.mtime != 0)
- time_print(client, "Last-Modified", info.mtime);
+ time_print(r, "Last-Modified", info.mtime);
}
return true;
@@ -98,52 +98,51 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
#endif
static bool
-handle_listfiles_storage(Client &client, Storage &storage, const char *uri,
+handle_listfiles_storage(Response &r, Storage &storage, const char *uri,
Error &error)
{
auto reader = storage.OpenDirectory(uri, error);
if (reader == nullptr)
return false;
- bool success = handle_listfiles_storage(client, *reader, error);
+ bool success = handle_listfiles_storage(r, *reader, error);
delete reader;
return success;
}
CommandResult
-handle_listfiles_storage(Client &client, Storage &storage, const char *uri)
+handle_listfiles_storage(Response &r, Storage &storage, const char *uri)
{
Error error;
- if (!handle_listfiles_storage(client, storage, uri, error))
- return print_error(client, error);
+ if (!handle_listfiles_storage(r, storage, uri, error))
+ return print_error(r, error);
return CommandResult::OK;
}
CommandResult
-handle_listfiles_storage(Client &client, const char *uri)
+handle_listfiles_storage(Response &r, const char *uri)
{
Error error;
Storage *storage = CreateStorageURI(io_thread_get(), uri, error);
if (storage == nullptr) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_ARG,
- "Unrecognized storage URI");
+ r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
return CommandResult::ERROR;
}
- bool success = handle_listfiles_storage(client, *storage, "", error);
+ bool success = handle_listfiles_storage(r, *storage, "", error);
delete storage;
if (!success)
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}
static void
-print_storage_uri(Client &client, const Storage &storage)
+print_storage_uri(Client &client, Response &r, const Storage &storage)
{
std::string uri = storage.MapUTF8("");
if (uri.empty())
@@ -165,24 +164,26 @@ print_storage_uri(Client &client, const Storage &storage)
uri = std::move(allocated);
}
- client_printf(client, "storage: %s\n", uri.c_str());
+ r.Format("storage: %s\n", uri.c_str());
}
CommandResult
handle_listmounts(Client &client, gcc_unused Request args)
{
+ Response r(client);
+
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
}
CompositeStorage &composite = *(CompositeStorage *)_composite;
- const auto visitor = [&client](const char *mount_uri,
- const Storage &storage){
- client_printf(client, "mount: %s\n", mount_uri);
- print_storage_uri(client, storage);
+ const auto visitor = [&client, &r](const char *mount_uri,
+ const Storage &storage){
+ r.Format("mount: %s\n", mount_uri);
+ print_storage_uri(client, r, storage);
};
composite.VisitMounts(visitor);
@@ -193,9 +194,11 @@ handle_listmounts(Client &client, gcc_unused Request args)
CommandResult
handle_mount(Client &client, Request args)
{
+ Response r(client);
+
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
}
@@ -205,7 +208,7 @@ handle_mount(Client &client, Request args)
const char *const remote_uri = args[1];
if (*local_uri == 0) {
- command_error(client, ACK_ERROR_ARG, "Bad mount point");
+ r.Error(ACK_ERROR_ARG, "Bad mount point");
return CommandResult::ERROR;
}
@@ -215,7 +218,7 @@ handle_mount(Client &client, Request args)
UpdateQueue::Erase() really gets called for every
unmount, and no Directory disappears recursively
during database update */
- command_error(client, ACK_ERROR_ARG, "Bad mount point");
+ r.Error(ACK_ERROR_ARG, "Bad mount point");
return CommandResult::ERROR;
}
@@ -224,10 +227,9 @@ handle_mount(Client &client, Request args)
error);
if (storage == nullptr) {
if (error.IsDefined())
- return print_error(client, error);
+ return print_error(r, error);
- command_error(client, ACK_ERROR_ARG,
- "Unrecognized storage URI");
+ r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
return CommandResult::ERROR;
}
@@ -241,7 +243,7 @@ handle_mount(Client &client, Request args)
if (!db.Mount(local_uri, remote_uri, error)) {
composite.Unmount(local_uri);
- return print_error(client, error);
+ return print_error(r, error);
}
// TODO: call Instance::OnDatabaseModified()?
@@ -256,9 +258,11 @@ handle_mount(Client &client, Request args)
CommandResult
handle_unmount(Client &client, Request args)
{
+ Response r(client);
+
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
- command_error(client, ACK_ERROR_NO_EXIST, "No database");
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
}
@@ -267,7 +271,7 @@ handle_unmount(Client &client, Request args)
const char *const local_uri = args.front();
if (*local_uri == 0) {
- command_error(client, ACK_ERROR_ARG, "Bad mount point");
+ r.Error(ACK_ERROR_ARG, "Bad mount point");
return CommandResult::ERROR;
}
@@ -289,7 +293,7 @@ handle_unmount(Client &client, Request args)
#endif
if (!composite.Unmount(local_uri)) {
- command_error(client, ACK_ERROR_ARG, "Not a mount point");
+ r.Error(ACK_ERROR_ARG, "Not a mount point");
return CommandResult::ERROR;
}
diff --git a/src/command/StorageCommands.hxx b/src/command/StorageCommands.hxx
index f5f962042..bbc0149bd 100644
--- a/src/command/StorageCommands.hxx
+++ b/src/command/StorageCommands.hxx
@@ -25,12 +25,13 @@
class Client;
class Storage;
class Request;
+class Response;
CommandResult
-handle_listfiles_storage(Client &client, Storage &storage, const char *uri);
+handle_listfiles_storage(Response &r, Storage &storage, const char *uri);
CommandResult
-handle_listfiles_storage(Client &client, const char *uri);
+handle_listfiles_storage(Response &r, const char *uri);
CommandResult
handle_listmounts(Client &client, Request args);
diff --git a/src/command/TagCommands.cxx b/src/command/TagCommands.cxx
index 2690f39bf..35efa5859 100644
--- a/src/command/TagCommands.cxx
+++ b/src/command/TagCommands.cxx
@@ -22,7 +22,7 @@
#include "Request.hxx"
#include "CommandError.hxx"
#include "client/Client.hxx"
-#include "protocol/Result.hxx"
+#include "client/Response.hxx"
#include "tag/Tag.hxx"
#include "Partition.hxx"
#include "util/ConstBuffer.hxx"
@@ -30,15 +30,16 @@
CommandResult
handle_addtagid(Client &client, Request args)
{
+ Response r(client);
+
unsigned song_id;
- if (!args.Parse(0, song_id, client))
+ if (!args.Parse(0, song_id, r))
return CommandResult::ERROR;
const char *const tag_name = args[1];
const TagType tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
- command_error(client, ACK_ERROR_ARG,
- "Unknown tag type: %s", tag_name);
+ r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", tag_name);
return CommandResult::ERROR;
}
@@ -47,7 +48,7 @@ handle_addtagid(Client &client, Request args)
Error error;
if (!client.partition.playlist.AddSongIdTag(song_id, tag_type, value,
error))
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}
@@ -55,8 +56,10 @@ handle_addtagid(Client &client, Request args)
CommandResult
handle_cleartagid(Client &client, Request args)
{
+ Response r(client);
+
unsigned song_id;
- if (!args.Parse(0, song_id, client))
+ if (!args.Parse(0, song_id, r))
return CommandResult::ERROR;
TagType tag_type = TAG_NUM_OF_ITEM_TYPES;
@@ -64,7 +67,7 @@ handle_cleartagid(Client &client, Request args)
const char *const tag_name = args[1];
tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
- command_error(client, ACK_ERROR_ARG,
+ r.FormatError(ACK_ERROR_ARG,
"Unknown tag type: %s", tag_name);
return CommandResult::ERROR;
}
@@ -73,7 +76,7 @@ handle_cleartagid(Client &client, Request args)
Error error;
if (!client.partition.playlist.ClearSongIdTag(song_id, tag_type,
error))
- return print_error(client, error);
+ return print_error(r, error);
return CommandResult::OK;
}