Commit 6edfc56c authored by Max Kellermann's avatar Max Kellermann

command: use ConstBuffer<const char *> for argument list

parent 5837a639
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "client/Client.hxx" #include "client/Client.hxx"
#include "util/Tokenizer.hxx" #include "util/Tokenizer.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#ifdef ENABLE_SQLITE #ifdef ENABLE_SQLITE
#include "StickerCommands.hxx" #include "StickerCommands.hxx"
...@@ -60,15 +61,15 @@ struct command { ...@@ -60,15 +61,15 @@ struct command {
unsigned permission; unsigned permission;
int min; int min;
int max; int max;
CommandResult (*handler)(Client &client, unsigned argc, char **argv); CommandResult (*handler)(Client &client, ConstBuffer<const char *> args);
}; };
/* don't be fooled, this is the command handler for "commands" command */ /* don't be fooled, this is the command handler for "commands" command */
static CommandResult static CommandResult
handle_commands(Client &client, unsigned argc, char *argv[]); handle_commands(Client &client, ConstBuffer<const char *> args);
static CommandResult static CommandResult
handle_not_commands(Client &client, unsigned argc, char *argv[]); handle_not_commands(Client &client, ConstBuffer<const char *> args);
/** /**
* The command registry. * The command registry.
...@@ -225,8 +226,7 @@ command_available(gcc_unused const Partition &partition, ...@@ -225,8 +226,7 @@ command_available(gcc_unused const Partition &partition,
/* don't be fooled, this is the command handler for "commands" command */ /* don't be fooled, this is the command handler for "commands" command */
static CommandResult static CommandResult
handle_commands(Client &client, handle_commands(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
const unsigned permission = client.GetPermission(); const unsigned permission = client.GetPermission();
...@@ -242,8 +242,7 @@ handle_commands(Client &client, ...@@ -242,8 +242,7 @@ handle_commands(Client &client,
} }
static CommandResult static CommandResult
handle_not_commands(Client &client, handle_not_commands(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
const unsigned permission = client.GetPermission(); const unsigned permission = client.GetPermission();
...@@ -293,11 +292,8 @@ command_lookup(const char *name) ...@@ -293,11 +292,8 @@ command_lookup(const char *name)
static bool static bool
command_check_request(const struct command *cmd, Client &client, command_check_request(const struct command *cmd, Client &client,
unsigned permission, unsigned argc, char *argv[]) unsigned permission, ConstBuffer<const char *> args)
{ {
const unsigned min = cmd->min + 1;
const unsigned max = cmd->max + 1;
if (cmd->permission != (permission & cmd->permission)) { if (cmd->permission != (permission & cmd->permission)) {
command_error(client, ACK_ERROR_PERMISSION, command_error(client, ACK_ERROR_PERMISSION,
"you don't have permission for \"%s\"", "you don't have permission for \"%s\"",
...@@ -305,21 +301,24 @@ command_check_request(const struct command *cmd, Client &client, ...@@ -305,21 +301,24 @@ command_check_request(const struct command *cmd, Client &client,
return false; return false;
} }
if (min == 0) const int min = cmd->min;
const int max = cmd->max;
if (min < 0)
return true; return true;
if (min == max && max != argc) { if (min == max && unsigned(max) != args.size) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"wrong number of arguments for \"%s\"", "wrong number of arguments for \"%s\"",
argv[0]); cmd->cmd);
return false; return false;
} else if (argc < min) { } else if (args.size < unsigned(min)) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"too few arguments for \"%s\"", argv[0]); "too few arguments for \"%s\"", cmd->cmd);
return false; return false;
} else if (argc > max && max /* != 0 */ ) { } else if (max >= 0 && args.size > unsigned(max)) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"too many arguments for \"%s\"", argv[0]); "too many arguments for \"%s\"", cmd->cmd);
return false; return false;
} else } else
return true; return true;
...@@ -327,23 +326,20 @@ command_check_request(const struct command *cmd, Client &client, ...@@ -327,23 +326,20 @@ command_check_request(const struct command *cmd, Client &client,
static const struct command * static const struct command *
command_checked_lookup(Client &client, unsigned permission, command_checked_lookup(Client &client, unsigned permission,
unsigned argc, char *argv[]) const char *cmd_name, ConstBuffer<const char *> args)
{ {
current_command = ""; current_command = "";
if (argc == 0) const struct command *cmd = command_lookup(cmd_name);
return nullptr;
const struct command *cmd = command_lookup(argv[0]);
if (cmd == nullptr) { if (cmd == nullptr) {
command_error(client, ACK_ERROR_UNKNOWN, command_error(client, ACK_ERROR_UNKNOWN,
"unknown command \"%s\"", argv[0]); "unknown command \"%s\"", cmd_name);
return nullptr; return nullptr;
} }
current_command = cmd->cmd; current_command = cmd->cmd;
if (!command_check_request(cmd, client, permission, argc, argv)) if (!command_check_request(cmd, client, permission, args))
return nullptr; return nullptr;
return cmd; return cmd;
...@@ -362,9 +358,9 @@ command_process(Client &client, unsigned num, char *line) ...@@ -362,9 +358,9 @@ command_process(Client &client, unsigned num, char *line)
Tokenizer tokenizer(line); Tokenizer tokenizer(line);
char *argv[COMMAND_ARGV_MAX]; const char *const cmd_name = current_command =
current_command = argv[0] = tokenizer.NextWord(error); tokenizer.NextWord(error);
if (argv[0] == nullptr) { if (cmd_name == nullptr) {
current_command = ""; current_command = "";
if (tokenizer.IsEnd()) if (tokenizer.IsEnd())
command_error(client, ACK_ERROR_UNKNOWN, command_error(client, ACK_ERROR_UNKNOWN,
...@@ -380,12 +376,13 @@ command_process(Client &client, unsigned num, char *line) ...@@ -380,12 +376,13 @@ command_process(Client &client, unsigned num, char *line)
return CommandResult::FINISH; return CommandResult::FINISH;
} }
unsigned argc = 1; char *argv[COMMAND_ARGV_MAX];
ConstBuffer<const char *> args(argv, 0);
/* now parse the arguments (quoted or unquoted) */ /* now parse the arguments (quoted or unquoted) */
while (true) { while (true) {
if (argc == COMMAND_ARGV_MAX) { if (args.size == COMMAND_ARGV_MAX) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"Too many arguments"); "Too many arguments");
current_command = nullptr; current_command = nullptr;
...@@ -402,17 +399,17 @@ command_process(Client &client, unsigned num, char *line) ...@@ -402,17 +399,17 @@ command_process(Client &client, unsigned num, char *line)
return CommandResult::ERROR; return CommandResult::ERROR;
} }
argv[argc++] = a; argv[args.size++] = a;
} }
/* look up and invoke the command handler */ /* look up and invoke the command handler */
const struct command *cmd = const struct command *cmd =
command_checked_lookup(client, client.GetPermission(), command_checked_lookup(client, client.GetPermission(),
argc, argv); cmd_name, args);
CommandResult ret = cmd CommandResult ret = cmd
? cmd->handler(client, argc, argv) ? cmd->handler(client, args)
: CommandResult::ERROR; : CommandResult::ERROR;
current_command = nullptr; current_command = nullptr;
......
...@@ -50,12 +50,10 @@ handle_listfiles_db(Client &client, const char *uri) ...@@ -50,12 +50,10 @@ handle_listfiles_db(Client &client, const char *uri)
} }
CommandResult CommandResult
handle_lsinfo2(Client &client, unsigned argc, char *argv[]) handle_lsinfo2(Client &client, ConstBuffer<const char *> args)
{ {
const char *const uri = argc == 2
? argv[1]
/* default is root directory */ /* default is root directory */
: ""; const char *const uri = args.IsEmpty() ? "" : args.front();
const DatabaseSelection selection(uri, false); const DatabaseSelection selection(uri, false);
...@@ -67,10 +65,8 @@ handle_lsinfo2(Client &client, unsigned argc, char *argv[]) ...@@ -67,10 +65,8 @@ handle_lsinfo2(Client &client, unsigned argc, char *argv[])
} }
static CommandResult static CommandResult
handle_match(Client &client, unsigned argc, char *argv[], bool fold_case) handle_match(Client &client, ConstBuffer<const char *> args, bool fold_case)
{ {
ConstBuffer<const char *> args(argv + 1, argc - 1);
unsigned window_start = 0, window_end = std::numeric_limits<int>::max(); unsigned window_start = 0, window_end = std::numeric_limits<int>::max();
if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) { if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) {
if (!check_range(client, &window_start, &window_end, if (!check_range(client, &window_start, &window_end,
...@@ -97,22 +93,20 @@ handle_match(Client &client, unsigned argc, char *argv[], bool fold_case) ...@@ -97,22 +93,20 @@ handle_match(Client &client, unsigned argc, char *argv[], bool fold_case)
} }
CommandResult CommandResult
handle_find(Client &client, unsigned argc, char *argv[]) handle_find(Client &client, ConstBuffer<const char *> args)
{ {
return handle_match(client, argc, argv, false); return handle_match(client, args, false);
} }
CommandResult CommandResult
handle_search(Client &client, unsigned argc, char *argv[]) handle_search(Client &client, ConstBuffer<const char *> args)
{ {
return handle_match(client, argc, argv, true); return handle_match(client, args, true);
} }
static CommandResult static CommandResult
handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case) handle_match_add(Client &client, ConstBuffer<const char *> args, bool fold_case)
{ {
ConstBuffer<const char *> args(argv + 1, argc - 1);
SongFilter filter; SongFilter filter;
if (!filter.Parse(args, fold_case)) { if (!filter.Parse(args, fold_case)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments"); command_error(client, ACK_ERROR_ARG, "incorrect arguments");
...@@ -129,21 +123,20 @@ handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case) ...@@ -129,21 +123,20 @@ handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case)
} }
CommandResult CommandResult
handle_findadd(Client &client, unsigned argc, char *argv[]) handle_findadd(Client &client, ConstBuffer<const char *> args)
{ {
return handle_match_add(client, argc, argv, false); return handle_match_add(client, args, false);
} }
CommandResult CommandResult
handle_searchadd(Client &client, unsigned argc, char *argv[]) handle_searchadd(Client &client, ConstBuffer<const char *> args)
{ {
return handle_match_add(client, argc, argv, true); return handle_match_add(client, args, true);
} }
CommandResult CommandResult
handle_searchaddpl(Client &client, unsigned argc, char *argv[]) handle_searchaddpl(Client &client, ConstBuffer<const char *> args)
{ {
ConstBuffer<const char *> args(argv + 1, argc - 1);
const char *playlist = args.shift(); const char *playlist = args.shift();
SongFilter filter; SongFilter filter;
...@@ -164,10 +157,8 @@ handle_searchaddpl(Client &client, unsigned argc, char *argv[]) ...@@ -164,10 +157,8 @@ handle_searchaddpl(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_count(Client &client, unsigned argc, char *argv[]) handle_count(Client &client, ConstBuffer<const char *> args)
{ {
ConstBuffer<const char *> args(argv + 1, argc - 1);
TagType group = TAG_NUM_OF_ITEM_TYPES; TagType group = TAG_NUM_OF_ITEM_TYPES;
if (args.size >= 2 && strcmp(args[args.size - 2], "group") == 0) { if (args.size >= 2 && strcmp(args[args.size - 2], "group") == 0) {
const char *s = args[args.size - 1]; const char *s = args[args.size - 1];
...@@ -195,24 +186,21 @@ handle_count(Client &client, unsigned argc, char *argv[]) ...@@ -195,24 +186,21 @@ handle_count(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_listall(Client &client, gcc_unused unsigned argc, char *argv[]) handle_listall(Client &client, ConstBuffer<const char *> args)
{ {
const char *directory = ""; /* default is root directory */
const char *const uri = args.IsEmpty() ? "" : args.front();
if (argc == 2)
directory = argv[1];
Error error; Error error;
return db_selection_print(client, DatabaseSelection(directory, true), return db_selection_print(client, DatabaseSelection(uri, true),
false, false, error) false, false, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_list(Client &client, unsigned argc, char *argv[]) handle_list(Client &client, ConstBuffer<const char *> args)
{ {
ConstBuffer<const char *> args(argv + 1, argc - 1);
const char *tag_name = args.shift(); const char *tag_name = args.shift();
unsigned tagType = locate_parse_type(tag_name); unsigned tagType = locate_parse_type(tag_name);
...@@ -283,15 +271,13 @@ handle_list(Client &client, unsigned argc, char *argv[]) ...@@ -283,15 +271,13 @@ handle_list(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_listallinfo(Client &client, gcc_unused unsigned argc, char *argv[]) handle_listallinfo(Client &client, ConstBuffer<const char *> args)
{ {
const char *directory = ""; /* default is root directory */
const char *const uri = args.IsEmpty() ? "" : args.front();
if (argc == 2)
directory = argv[1];
Error error; Error error;
return db_selection_print(client, DatabaseSelection(directory, true), return db_selection_print(client, DatabaseSelection(uri, true),
true, false, error) true, false, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
......
...@@ -23,38 +23,39 @@ ...@@ -23,38 +23,39 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_listfiles_db(Client &client, const char *uri); handle_listfiles_db(Client &client, const char *uri);
CommandResult CommandResult
handle_lsinfo2(Client &client, unsigned argc, char *argv[]); handle_lsinfo2(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_find(Client &client, unsigned argc, char *argv[]); handle_find(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_findadd(Client &client, unsigned argc, char *argv[]); handle_findadd(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_search(Client &client, unsigned argc, char *argv[]); handle_search(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_searchadd(Client &client, unsigned argc, char *argv[]); handle_searchadd(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_searchaddpl(Client &client, unsigned argc, char *argv[]); handle_searchaddpl(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_count(Client &client, unsigned argc, char *argv[]); handle_count(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listall(Client &client, unsigned argc, char *argv[]); handle_listall(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_list(Client &client, unsigned argc, char *argv[]); handle_list(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listallinfo(Client &client, unsigned argc, char *argv[]); handle_listallinfo(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "protocol/Ack.hxx" #include "protocol/Ack.hxx"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "client/Client.hxx" #include "client/Client.hxx"
#include "util/ConstBuffer.hxx"
#include "util/CharUtil.hxx" #include "util/CharUtil.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
...@@ -202,11 +203,10 @@ read_file_comments(Client &client, const Path path_fs) ...@@ -202,11 +203,10 @@ read_file_comments(Client &client, const Path path_fs)
} }
CommandResult CommandResult
handle_read_comments(Client &client, gcc_unused unsigned argc, char *argv[]) handle_read_comments(Client &client, ConstBuffer<const char *> args)
{ {
assert(argc == 2); assert(args.size == 1);
const char *const uri = args.front();
const char *const uri = argv[1];
if (memcmp(uri, "file:///", 8) == 0) { if (memcmp(uri, "file:///", 8) == 0) {
/* read comments from arbitrary local file */ /* read comments from arbitrary local file */
......
...@@ -23,11 +23,12 @@ ...@@ -23,11 +23,12 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_listfiles_local(Client &client, const char *path_utf8); handle_listfiles_local(Client &client, const char *path_utf8);
CommandResult CommandResult
handle_read_comments(Client &client, unsigned argc, char *argv[]); handle_read_comments(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "Instance.hxx" #include "Instance.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "util/ConstBuffer.hxx"
#include <set> #include <set>
#include <string> #include <string>
...@@ -31,11 +32,12 @@ ...@@ -31,11 +32,12 @@
#include <assert.h> #include <assert.h>
CommandResult CommandResult
handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[]) handle_subscribe(Client &client, ConstBuffer<const char *> args)
{ {
assert(argc == 2); assert(args.size == 1);
const char *const channel_name = args[0];
switch (client.Subscribe(argv[1])) { switch (client.Subscribe(channel_name)) {
case Client::SubscribeResult::OK: case Client::SubscribeResult::OK:
return CommandResult::OK; return CommandResult::OK;
...@@ -61,11 +63,12 @@ handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -61,11 +63,12 @@ handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[]) handle_unsubscribe(Client &client, ConstBuffer<const char *> args)
{ {
assert(argc == 2); assert(args.size == 1);
const char *const channel_name = args[0];
if (client.Unsubscribe(argv[1])) if (client.Unsubscribe(channel_name))
return CommandResult::OK; return CommandResult::OK;
else { else {
command_error(client, ACK_ERROR_NO_EXIST, command_error(client, ACK_ERROR_NO_EXIST,
...@@ -75,10 +78,9 @@ handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -75,10 +78,9 @@ handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_channels(Client &client, handle_channels(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
assert(argc == 1); assert(args.IsEmpty());
std::set<std::string> channels; std::set<std::string> channels;
for (const auto &c : *client.partition.instance.client_list) for (const auto &c : *client.partition.instance.client_list)
...@@ -93,9 +95,9 @@ handle_channels(Client &client, ...@@ -93,9 +95,9 @@ handle_channels(Client &client,
CommandResult CommandResult
handle_read_messages(Client &client, handle_read_messages(Client &client,
gcc_unused unsigned argc, gcc_unused char *argv[]) gcc_unused ConstBuffer<const char *> args)
{ {
assert(argc == 1); assert(args.IsEmpty());
while (!client.messages.empty()) { while (!client.messages.empty()) {
const ClientMessage &msg = client.messages.front(); const ClientMessage &msg = client.messages.front();
...@@ -109,19 +111,21 @@ handle_read_messages(Client &client, ...@@ -109,19 +111,21 @@ handle_read_messages(Client &client,
} }
CommandResult CommandResult
handle_send_message(Client &client, handle_send_message(Client &client, ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
assert(argc == 3); assert(args.size == 2);
if (!client_message_valid_channel_name(argv[1])) { const char *const channel_name = args[0];
const char *const message_text = args[1];
if (!client_message_valid_channel_name(channel_name)) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"invalid channel name"); "invalid channel name");
return CommandResult::ERROR; return CommandResult::ERROR;
} }
bool sent = false; bool sent = false;
const ClientMessage msg(argv[1], argv[2]); const ClientMessage msg(channel_name, message_text);
for (auto &c : *client.partition.instance.client_list) for (auto &c : *client.partition.instance.client_list)
if (c.PushMessage(msg)) if (c.PushMessage(msg))
sent = true; sent = true;
......
...@@ -23,20 +23,21 @@ ...@@ -23,20 +23,21 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_subscribe(Client &client, unsigned argc, char *argv[]); handle_subscribe(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_unsubscribe(Client &client, unsigned argc, char *argv[]); handle_unsubscribe(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_channels(Client &client, unsigned argc, char *argv[]); handle_channels(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_read_messages(Client &client, unsigned argc, char *argv[]); handle_read_messages(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_send_message(Client &client, unsigned argc, char *argv[]); handle_send_message(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "neighbor/Glue.hxx" #include "neighbor/Glue.hxx"
#include "neighbor/Info.hxx" #include "neighbor/Info.hxx"
#include "util/ConstBuffer.hxx"
#include <set> #include <set>
#include <string> #include <string>
...@@ -38,8 +39,7 @@ neighbor_commands_available(const Instance &instance) ...@@ -38,8 +39,7 @@ neighbor_commands_available(const Instance &instance)
} }
CommandResult CommandResult
handle_listneighbors(Client &client, handle_listneighbors(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
const NeighborGlue *const neighbors = const NeighborGlue *const neighbors =
client.partition.instance.neighbors; client.partition.instance.neighbors;
......
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
struct Instance; struct Instance;
class Client; class Client;
template<typename T> struct ConstBuffer;
gcc_pure gcc_pure
bool bool
neighbor_commands_available(const Instance &instance); neighbor_commands_available(const Instance &instance);
CommandResult CommandResult
handle_listneighbors(Client &client, unsigned argc, char *argv[]); handle_listneighbors(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "mixer/Volume.hxx" #include "mixer/Volume.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "Stats.hxx" #include "Stats.hxx"
#include "Permission.hxx" #include "Permission.hxx"
...@@ -68,8 +69,7 @@ print_spl_list(Client &client, const PlaylistVector &list) ...@@ -68,8 +69,7 @@ print_spl_list(Client &client, const PlaylistVector &list)
} }
CommandResult CommandResult
handle_urlhandlers(Client &client, handle_urlhandlers(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
if (client.IsLocal()) if (client.IsLocal())
client_puts(client, "handler: file://\n"); client_puts(client, "handler: file://\n");
...@@ -78,31 +78,27 @@ handle_urlhandlers(Client &client, ...@@ -78,31 +78,27 @@ handle_urlhandlers(Client &client,
} }
CommandResult CommandResult
handle_decoders(Client &client, handle_decoders(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
decoder_list_print(client); decoder_list_print(client);
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_tagtypes(Client &client, handle_tagtypes(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
tag_print_types(client); tag_print_types(client);
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_kill(gcc_unused Client &client, handle_kill(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
return CommandResult::KILL; return CommandResult::KILL;
} }
CommandResult CommandResult
handle_close(gcc_unused Client &client, handle_close(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
return CommandResult::FINISH; return CommandResult::FINISH;
} }
...@@ -116,12 +112,10 @@ print_tag(TagType type, const char *value, void *ctx) ...@@ -116,12 +112,10 @@ print_tag(TagType type, const char *value, void *ctx)
} }
CommandResult CommandResult
handle_listfiles(Client &client, unsigned argc, char *argv[]) handle_listfiles(Client &client, ConstBuffer<const char *> args)
{ {
const char *const uri = argc == 2
? argv[1]
/* default is root directory */ /* default is root directory */
: ""; const char *const uri = args.IsEmpty() ? "" : args.front();
if (memcmp(uri, "file:///", 8) == 0) if (memcmp(uri, "file:///", 8) == 0)
/* list local directory */ /* list local directory */
...@@ -157,12 +151,10 @@ static constexpr tag_handler print_tag_handler = { ...@@ -157,12 +151,10 @@ static constexpr tag_handler print_tag_handler = {
}; };
CommandResult CommandResult
handle_lsinfo(Client &client, unsigned argc, char *argv[]) handle_lsinfo(Client &client, ConstBuffer<const char *> args)
{ {
const char *const uri = argc == 2
? argv[1]
/* default is root directory */ /* default is root directory */
: ""; const char *const uri = args.IsEmpty() ? "" : args.front();
if (memcmp(uri, "file:///", 8) == 0) { if (memcmp(uri, "file:///", 8) == 0) {
/* print information about an arbitrary local file */ /* print information about an arbitrary local file */
...@@ -207,7 +199,7 @@ handle_lsinfo(Client &client, unsigned argc, char *argv[]) ...@@ -207,7 +199,7 @@ handle_lsinfo(Client &client, unsigned argc, char *argv[])
} }
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
CommandResult result = handle_lsinfo2(client, argc, argv); CommandResult result = handle_lsinfo2(client, args);
if (result != CommandResult::OK) if (result != CommandResult::OK)
return result; return result;
#endif #endif
...@@ -265,14 +257,14 @@ handle_update(Client &client, Database &db, ...@@ -265,14 +257,14 @@ handle_update(Client &client, Database &db,
#endif #endif
static CommandResult static CommandResult
handle_update(Client &client, unsigned argc, char *argv[], bool discard) handle_update(Client &client, ConstBuffer<const char *> args, bool discard)
{ {
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const char *path = ""; const char *path = "";
assert(argc <= 2); assert(args.size <= 1);
if (argc == 2) { if (!args.IsEmpty()) {
path = argv[1]; path = args.front();
if (*path == 0 || strcmp(path, "/") == 0) if (*path == 0 || strcmp(path, "/") == 0)
/* backwards compatibility with MPD 0.15 */ /* backwards compatibility with MPD 0.15 */
...@@ -292,8 +284,7 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard) ...@@ -292,8 +284,7 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard)
if (db != nullptr) if (db != nullptr)
return handle_update(client, *db, path, discard); return handle_update(client, *db, path, discard);
#else #else
(void)argc; (void)args;
(void)argv;
(void)discard; (void)discard;
#endif #endif
...@@ -302,24 +293,24 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard) ...@@ -302,24 +293,24 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard)
} }
CommandResult CommandResult
handle_update(Client &client, gcc_unused unsigned argc, char *argv[]) handle_update(Client &client, gcc_unused ConstBuffer<const char *> args)
{ {
return handle_update(client, argc, argv, false); return handle_update(client, args, false);
} }
CommandResult CommandResult
handle_rescan(Client &client, gcc_unused unsigned argc, char *argv[]) handle_rescan(Client &client, gcc_unused ConstBuffer<const char *> args)
{ {
return handle_update(client, argc, argv, true); return handle_update(client, args, true);
} }
CommandResult CommandResult
handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[]) handle_setvol(Client &client, ConstBuffer<const char *> args)
{ {
unsigned level; unsigned level;
bool success; bool success;
if (!check_unsigned(client, &level, argv[1])) if (!check_unsigned(client, &level, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (level > 100) { if (level > 100) {
...@@ -338,10 +329,10 @@ handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -338,10 +329,10 @@ handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_volume(Client &client, gcc_unused unsigned argc, char *argv[]) handle_volume(Client &client, ConstBuffer<const char *> args)
{ {
int relative; int relative;
if (!check_int(client, &relative, argv[1])) if (!check_int(client, &relative, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (relative < -100 || relative > 100) { if (relative < -100 || relative > 100) {
...@@ -372,26 +363,24 @@ handle_volume(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -372,26 +363,24 @@ handle_volume(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_stats(Client &client, handle_stats(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
stats_print(client); stats_print(client);
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_ping(gcc_unused Client &client, handle_ping(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_password(Client &client, gcc_unused unsigned argc, char *argv[]) handle_password(Client &client, ConstBuffer<const char *> args)
{ {
unsigned permission = 0; unsigned permission = 0;
if (getPermissionFromPassword(argv[1], &permission) < 0) { if (getPermissionFromPassword(args.front(), &permission) < 0) {
command_error(client, ACK_ERROR_PASSWORD, "incorrect password"); command_error(client, ACK_ERROR_PASSWORD, "incorrect password");
return CommandResult::ERROR; return CommandResult::ERROR;
} }
...@@ -402,8 +391,7 @@ handle_password(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -402,8 +391,7 @@ handle_password(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_config(Client &client, handle_config(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
if (!client.IsLocal()) { if (!client.IsLocal()) {
command_error(client, ACK_ERROR_PERMISSION, command_error(client, ACK_ERROR_PERMISSION,
...@@ -423,17 +411,16 @@ handle_config(Client &client, ...@@ -423,17 +411,16 @@ handle_config(Client &client,
} }
CommandResult CommandResult
handle_idle(Client &client, handle_idle(Client &client, ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
unsigned flags = 0; unsigned flags = 0;
for (unsigned i = 1; i < argc; ++i) { for (const char *i : args) {
unsigned event = idle_parse_name(argv[i]); unsigned event = idle_parse_name(i);
if (event == 0) { if (event == 0) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"Unrecognized idle event: %s", "Unrecognized idle event: %s",
argv[i]); i);
return CommandResult::ERROR; return CommandResult::ERROR;
} }
......
...@@ -23,53 +23,54 @@ ...@@ -23,53 +23,54 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_urlhandlers(Client &client, unsigned argc, char *argv[]); handle_urlhandlers(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_decoders(Client &client, unsigned argc, char *argv[]); handle_decoders(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_tagtypes(Client &client, unsigned argc, char *argv[]); handle_tagtypes(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_kill(Client &client, unsigned argc, char *argv[]); handle_kill(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_close(Client &client, unsigned argc, char *argv[]); handle_close(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listfiles(Client &client, unsigned argc, char *argv[]); handle_listfiles(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_lsinfo(Client &client, unsigned argc, char *argv[]); handle_lsinfo(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_update(Client &client, unsigned argc, char *argv[]); handle_update(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_rescan(Client &client, unsigned argc, char *argv[]); handle_rescan(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_setvol(Client &client, unsigned argc, char *argv[]); handle_setvol(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_volume(Client &client, unsigned argc, char *argv[]); handle_volume(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_stats(Client &client, unsigned argc, char *argv[]); handle_stats(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_ping(Client &client, unsigned argc, char *argv[]); handle_ping(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_password(Client &client, unsigned argc, char *argv[]); handle_password(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_config(Client &client, unsigned argc, char *argv[]); handle_config(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_idle(Client &client, unsigned argc, char *argv[]); handle_idle(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -25,12 +25,15 @@ ...@@ -25,12 +25,15 @@
#include "protocol/ArgParser.hxx" #include "protocol/ArgParser.hxx"
#include "client/Client.hxx" #include "client/Client.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include "util/ConstBuffer.hxx"
CommandResult CommandResult
handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) handle_enableoutput(Client &client, ConstBuffer<const char *> args)
{ {
assert(args.size == 1);
unsigned device; unsigned device;
if (!check_unsigned(client, &device, argv[1])) if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!audio_output_enable_index(client.partition.outputs, device)) { if (!audio_output_enable_index(client.partition.outputs, device)) {
...@@ -43,10 +46,12 @@ handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -43,10 +46,12 @@ handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) handle_disableoutput(Client &client, ConstBuffer<const char *> args)
{ {
assert(args.size == 1);
unsigned device; unsigned device;
if (!check_unsigned(client, &device, argv[1])) if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!audio_output_disable_index(client.partition.outputs, device)) { if (!audio_output_disable_index(client.partition.outputs, device)) {
...@@ -59,10 +64,12 @@ handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -59,10 +64,12 @@ handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[]) handle_toggleoutput(Client &client, ConstBuffer<const char *> args)
{ {
assert(args.size == 1);
unsigned device; unsigned device;
if (!check_unsigned(client, &device, argv[1])) if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!audio_output_toggle_index(client.partition.outputs, device)) { if (!audio_output_toggle_index(client.partition.outputs, device)) {
...@@ -75,9 +82,10 @@ handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -75,9 +82,10 @@ handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_devices(Client &client, handle_devices(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
assert(args.IsEmpty());
printAudioDevices(client, client.partition.outputs); printAudioDevices(client, client.partition.outputs);
return CommandResult::OK; return CommandResult::OK;
......
...@@ -23,17 +23,18 @@ ...@@ -23,17 +23,18 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_enableoutput(Client &client, unsigned argc, char *argv[]); handle_enableoutput(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_disableoutput(Client &client, unsigned argc, char *argv[]); handle_disableoutput(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_toggleoutput(Client &client, unsigned argc, char *argv[]); handle_toggleoutput(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_devices(Client &client, unsigned argc, char *argv[]); handle_devices(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "protocol/ArgParser.hxx" #include "protocol/ArgParser.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "ReplayGainConfig.hxx" #include "ReplayGainConfig.hxx"
#include "util/ConstBuffer.hxx"
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
#include "db/update/Service.hxx" #include "db/update/Service.hxx"
...@@ -56,22 +57,22 @@ ...@@ -56,22 +57,22 @@
#define COMMAND_STATUS_UPDATING_DB "updating_db" #define COMMAND_STATUS_UPDATING_DB "updating_db"
CommandResult CommandResult
handle_play(Client &client, unsigned argc, char *argv[]) handle_play(Client &client, ConstBuffer<const char *> args)
{ {
int song = -1; int song = -1;
if (argc == 2 && !check_int(client, &song, argv[1])) if (!args.IsEmpty() && !check_int(client, &song, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayPosition(song); PlaylistResult result = client.partition.PlayPosition(song);
return print_playlist_result(client, result); return print_playlist_result(client, result);
} }
CommandResult CommandResult
handle_playid(Client &client, unsigned argc, char *argv[]) handle_playid(Client &client, ConstBuffer<const char *> args)
{ {
int id = -1; int id = -1;
if (argc == 2 && !check_int(client, &id, argv[1])) if (!args.IsEmpty() && !check_int(client, &id, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayId(id); PlaylistResult result = client.partition.PlayId(id);
...@@ -79,28 +80,25 @@ handle_playid(Client &client, unsigned argc, char *argv[]) ...@@ -79,28 +80,25 @@ handle_playid(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_stop(Client &client, handle_stop(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
client.partition.Stop(); client.partition.Stop();
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_currentsong(Client &client, handle_currentsong(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
playlist_print_current(client, client.playlist); playlist_print_current(client, client.playlist);
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_pause(Client &client, handle_pause(Client &client, ConstBuffer<const char *> args)
unsigned argc, char *argv[])
{ {
if (argc == 2) { if (!args.IsEmpty()) {
bool pause_flag; bool pause_flag;
if (!check_bool(client, &pause_flag, argv[1])) if (!check_bool(client, &pause_flag, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.player_control.SetPause(pause_flag); client.player_control.SetPause(pause_flag);
...@@ -111,8 +109,7 @@ handle_pause(Client &client, ...@@ -111,8 +109,7 @@ handle_pause(Client &client,
} }
CommandResult CommandResult
handle_status(Client &client, handle_status(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
const char *state = nullptr; const char *state = nullptr;
int song; int song;
...@@ -226,8 +223,7 @@ handle_status(Client &client, ...@@ -226,8 +223,7 @@ handle_status(Client &client,
} }
CommandResult CommandResult
handle_next(Client &client, handle_next(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
playlist &playlist = client.playlist; playlist &playlist = client.playlist;
...@@ -243,18 +239,17 @@ handle_next(Client &client, ...@@ -243,18 +239,17 @@ handle_next(Client &client,
} }
CommandResult CommandResult
handle_previous(Client &client, handle_previous(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
client.partition.PlayPrevious(); client.partition.PlayPrevious();
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[]) handle_repeat(Client &client, ConstBuffer<const char *> args)
{ {
bool status; bool status;
if (!check_bool(client, &status, argv[1])) if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.partition.SetRepeat(status); client.partition.SetRepeat(status);
...@@ -262,10 +257,10 @@ handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -262,10 +257,10 @@ handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_single(Client &client, gcc_unused unsigned argc, char *argv[]) handle_single(Client &client, ConstBuffer<const char *> args)
{ {
bool status; bool status;
if (!check_bool(client, &status, argv[1])) if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.partition.SetSingle(status); client.partition.SetSingle(status);
...@@ -273,10 +268,10 @@ handle_single(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -273,10 +268,10 @@ handle_single(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_consume(Client &client, gcc_unused unsigned argc, char *argv[]) handle_consume(Client &client, ConstBuffer<const char *> args)
{ {
bool status; bool status;
if (!check_bool(client, &status, argv[1])) if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.partition.SetConsume(status); client.partition.SetConsume(status);
...@@ -284,10 +279,10 @@ handle_consume(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -284,10 +279,10 @@ handle_consume(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_random(Client &client, gcc_unused unsigned argc, char *argv[]) handle_random(Client &client, ConstBuffer<const char *> args)
{ {
bool status; bool status;
if (!check_bool(client, &status, argv[1])) if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.partition.SetRandom(status); client.partition.SetRandom(status);
...@@ -296,22 +291,21 @@ handle_random(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -296,22 +291,21 @@ handle_random(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_clearerror(gcc_unused Client &client, handle_clearerror(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
client.player_control.ClearError(); client.player_control.ClearError();
return CommandResult::OK; return CommandResult::OK;
} }
CommandResult CommandResult
handle_seek(Client &client, gcc_unused unsigned argc, char *argv[]) handle_seek(Client &client, ConstBuffer<const char *> args)
{ {
unsigned song; unsigned song;
SongTime seek_time; SongTime seek_time;
if (!check_unsigned(client, &song, argv[1])) if (!check_unsigned(client, &song, args[0]))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!ParseCommandArg(client, seek_time, argv[2])) if (!ParseCommandArg(client, seek_time, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = PlaylistResult result =
...@@ -320,14 +314,14 @@ handle_seek(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -320,14 +314,14 @@ handle_seek(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[]) handle_seekid(Client &client, ConstBuffer<const char *> args)
{ {
unsigned id; unsigned id;
SongTime seek_time; SongTime seek_time;
if (!check_unsigned(client, &id, argv[1])) if (!check_unsigned(client, &id, args[0]))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!ParseCommandArg(client, seek_time, argv[2])) if (!ParseCommandArg(client, seek_time, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = PlaylistResult result =
...@@ -336,9 +330,9 @@ handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -336,9 +330,9 @@ handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[]) handle_seekcur(Client &client, ConstBuffer<const char *> args)
{ {
const char *p = argv[1]; const char *p = args.front();
bool relative = *p == '+' || *p == '-'; bool relative = *p == '+' || *p == '-';
SignedSongTime seek_time; SignedSongTime seek_time;
if (!ParseCommandArg(client, seek_time, p)) if (!ParseCommandArg(client, seek_time, p))
...@@ -350,11 +344,11 @@ handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -350,11 +344,11 @@ handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[]) handle_crossfade(Client &client, ConstBuffer<const char *> args)
{ {
unsigned xfade_time; unsigned xfade_time;
if (!check_unsigned(client, &xfade_time, argv[1])) if (!check_unsigned(client, &xfade_time, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.player_control.SetCrossFade(xfade_time); client.player_control.SetCrossFade(xfade_time);
...@@ -362,11 +356,11 @@ handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -362,11 +356,11 @@ handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[]) handle_mixrampdb(Client &client, ConstBuffer<const char *> args)
{ {
float db; float db;
if (!check_float(client, &db, argv[1])) if (!check_float(client, &db, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.player_control.SetMixRampDb(db); client.player_control.SetMixRampDb(db);
...@@ -374,11 +368,11 @@ handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -374,11 +368,11 @@ handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[]) handle_mixrampdelay(Client &client, ConstBuffer<const char *> args)
{ {
float delay_secs; float delay_secs;
if (!check_float(client, &delay_secs, argv[1])) if (!check_float(client, &delay_secs, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.player_control.SetMixRampDelay(delay_secs); client.player_control.SetMixRampDelay(delay_secs);
...@@ -386,10 +380,9 @@ handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -386,10 +380,9 @@ handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_replay_gain_mode(Client &client, handle_replay_gain_mode(Client &client, ConstBuffer<const char *> args)
gcc_unused unsigned argc, char *argv[])
{ {
if (!replay_gain_set_mode_string(argv[1])) { if (!replay_gain_set_mode_string(args.front())) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"Unrecognized replay gain mode"); "Unrecognized replay gain mode");
return CommandResult::ERROR; return CommandResult::ERROR;
...@@ -400,8 +393,7 @@ handle_replay_gain_mode(Client &client, ...@@ -400,8 +393,7 @@ handle_replay_gain_mode(Client &client,
} }
CommandResult CommandResult
handle_replay_gain_status(Client &client, handle_replay_gain_status(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
client_printf(client, "replay_gain_mode: %s\n", client_printf(client, "replay_gain_mode: %s\n",
replay_gain_get_mode_string()); replay_gain_get_mode_string());
......
...@@ -23,68 +23,69 @@ ...@@ -23,68 +23,69 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_play(Client &client, unsigned argc, char *argv[]); handle_play(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playid(Client &client, unsigned argc, char *argv[]); handle_playid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_stop(Client &client, unsigned argc, char *argv[]); handle_stop(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_currentsong(Client &client, unsigned argc, char *argv[]); handle_currentsong(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_pause(Client &client, unsigned argc, char *argv[]); handle_pause(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_status(Client &client, unsigned argc, char *argv[]); handle_status(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_next(Client &client, unsigned argc, char *argv[]); handle_next(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_previous(Client &client, unsigned argc, char *avg[]); handle_previous(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_repeat(Client &client, unsigned argc, char *argv[]); handle_repeat(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_single(Client &client, unsigned argc, char *argv[]); handle_single(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_consume(Client &client, unsigned argc, char *argv[]); handle_consume(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_random(Client &client, unsigned argc, char *argv[]); handle_random(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_clearerror(Client &client, unsigned argc, char *argv[]); handle_clearerror(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_seek(Client &client, unsigned argc, char *argv[]); handle_seek(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_seekid(Client &client, unsigned argc, char *argv[]); handle_seekid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_seekcur(Client &client, unsigned argc, char *argv[]); handle_seekcur(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_crossfade(Client &client, unsigned argc, char *argv[]); handle_crossfade(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_mixrampdb(Client &client, unsigned argc, char *argv[]); handle_mixrampdb(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_mixrampdelay(Client &client, unsigned argc, char *argv[]); handle_mixrampdelay(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_replay_gain_mode(Client &client, unsigned argc, char *argv[]); handle_replay_gain_mode(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_replay_gain_status(Client &client, unsigned argc, char *argv[]); handle_replay_gain_status(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
bool bool
playlist_commands_available() playlist_commands_available()
...@@ -58,28 +59,28 @@ print_spl_list(Client &client, const PlaylistVector &list) ...@@ -58,28 +59,28 @@ print_spl_list(Client &client, const PlaylistVector &list)
} }
CommandResult CommandResult
handle_save(Client &client, gcc_unused unsigned argc, char *argv[]) handle_save(Client &client, ConstBuffer<const char *> args)
{ {
PlaylistResult result = spl_save_playlist(argv[1], client.playlist); PlaylistResult result = spl_save_playlist(args.front(), client.playlist);
return print_playlist_result(client, result); return print_playlist_result(client, result);
} }
CommandResult CommandResult
handle_load(Client &client, unsigned argc, char *argv[]) handle_load(Client &client, ConstBuffer<const char *> args)
{ {
unsigned start_index, end_index; unsigned start_index, end_index;
if (argc < 3) { if (args.size < 2) {
start_index = 0; start_index = 0;
end_index = unsigned(-1); end_index = unsigned(-1);
} else if (!check_range(client, &start_index, &end_index, argv[2])) } else if (!check_range(client, &start_index, &end_index, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
const ScopeBulkEdit bulk_edit(client.partition); const ScopeBulkEdit bulk_edit(client.partition);
Error error; Error error;
const SongLoader loader(client); const SongLoader loader(client);
if (!playlist_open_into_queue(argv[1], if (!playlist_open_into_queue(args.front(),
start_index, end_index, start_index, end_index,
client.playlist, client.playlist,
client.player_control, loader, error)) client.player_control, loader, error))
...@@ -89,94 +90,104 @@ handle_load(Client &client, unsigned argc, char *argv[]) ...@@ -89,94 +90,104 @@ handle_load(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_listplaylist(Client &client, gcc_unused unsigned argc, char *argv[]) handle_listplaylist(Client &client, ConstBuffer<const char *> args)
{ {
if (playlist_file_print(client, argv[1], false)) const char *const name = args.front();
if (playlist_file_print(client, name, false))
return CommandResult::OK; return CommandResult::OK;
Error error; Error error;
return spl_print(client, argv[1], false, error) return spl_print(client, name, false, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_listplaylistinfo(Client &client, handle_listplaylistinfo(Client &client, ConstBuffer<const char *> args)
gcc_unused unsigned argc, char *argv[])
{ {
if (playlist_file_print(client, argv[1], true)) const char *const name = args.front();
if (playlist_file_print(client, name, true))
return CommandResult::OK; return CommandResult::OK;
Error error; Error error;
return spl_print(client, argv[1], true, error) return spl_print(client, name, true, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_rm(Client &client, gcc_unused unsigned argc, char *argv[]) handle_rm(Client &client, ConstBuffer<const char *> args)
{ {
const char *const name = args.front();
Error error; Error error;
return spl_delete(argv[1], error) return spl_delete(name, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_rename(Client &client, gcc_unused unsigned argc, char *argv[]) handle_rename(Client &client, ConstBuffer<const char *> args)
{ {
const char *const old_name = args[0];
const char *const new_name = args[1];
Error error; Error error;
return spl_rename(argv[1], argv[2], error) return spl_rename(old_name, new_name, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_playlistdelete(Client &client, handle_playlistdelete(Client &client, ConstBuffer<const char *> args)
gcc_unused unsigned argc, char *argv[]) { {
char *playlist = argv[1]; const char *const name = args[0];
unsigned from; unsigned from;
if (!check_unsigned(client, &from, argv[2])) if (!check_unsigned(client, &from, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
Error error; Error error;
return spl_remove_index(playlist, from, error) return spl_remove_index(name, from, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_playlistmove(Client &client, gcc_unused unsigned argc, char *argv[]) handle_playlistmove(Client &client, ConstBuffer<const char *> args)
{ {
char *playlist = argv[1]; const char *const name = args.front();
unsigned from, to; unsigned from, to;
if (!check_unsigned(client, &from, argv[2])) if (!check_unsigned(client, &from, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!check_unsigned(client, &to, argv[3])) if (!check_unsigned(client, &to, args[2]))
return CommandResult::ERROR; return CommandResult::ERROR;
Error error; Error error;
return spl_move_index(playlist, from, to, error) return spl_move_index(name, from, to, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_playlistclear(Client &client, gcc_unused unsigned argc, char *argv[]) handle_playlistclear(Client &client, ConstBuffer<const char *> args)
{ {
const char *const name = args.front();
Error error; Error error;
return spl_clear(argv[1], error) return spl_clear(name, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }
CommandResult CommandResult
handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[]) handle_playlistadd(Client &client, ConstBuffer<const char *> args)
{ {
char *playlist = argv[1]; const char *const playlist = args[0];
char *uri = argv[2]; const char *const uri = args[1];
bool success; bool success;
Error error; Error error;
...@@ -207,8 +218,7 @@ handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -207,8 +218,7 @@ handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_listplaylists(Client &client, handle_listplaylists(Client &client, gcc_unused ConstBuffer<const char *> args)
gcc_unused unsigned argc, gcc_unused char *argv[])
{ {
Error error; Error error;
const auto list = ListPlaylistFiles(error); const auto list = ListPlaylistFiles(error);
......
...@@ -24,42 +24,43 @@ ...@@ -24,42 +24,43 @@
#include "Compiler.h" #include "Compiler.h"
class Client; class Client;
template<typename T> struct ConstBuffer;
gcc_const gcc_const
bool bool
playlist_commands_available(); playlist_commands_available();
CommandResult CommandResult
handle_save(Client &client, unsigned argc, char *argv[]); handle_save(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_load(Client &client, unsigned argc, char *argv[]); handle_load(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listplaylist(Client &client, unsigned argc, char *argv[]); handle_listplaylist(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listplaylistinfo(Client &client, unsigned argc, char *argv[]); handle_listplaylistinfo(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_rm(Client &client, unsigned argc, char *argv[]); handle_rm(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_rename(Client &client, unsigned argc, char *argv[]); handle_rename(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistdelete(Client &client, unsigned argc, char *argv[]); handle_playlistdelete(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistmove(Client &client, unsigned argc, char *argv[]); handle_playlistmove(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistclear(Client &client, unsigned argc, char *argv[]); handle_playlistclear(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistadd(Client &client, unsigned argc, char *argv[]); handle_playlistadd(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_listplaylists(Client &client, unsigned argc, char *argv[]); handle_listplaylists(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -23,65 +23,66 @@ ...@@ -23,65 +23,66 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_add(Client &client, unsigned argc, char *argv[]); handle_add(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_addid(Client &client, unsigned argc, char *argv[]); handle_addid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_rangeid(Client &client, unsigned argc, char *argv[]); handle_rangeid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_delete(Client &client, unsigned argc, char *argv[]); handle_delete(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_deleteid(Client &client, unsigned argc, char *argv[]); handle_deleteid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlist(Client &client, unsigned argc, char *argv[]); handle_playlist(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_shuffle(Client &client, unsigned argc, char *argv[]); handle_shuffle(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_clear(Client &client, unsigned argc, char *argv[]); handle_clear(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_plchanges(Client &client, unsigned argc, char *argv[]); handle_plchanges(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_plchangesposid(Client &client, unsigned argc, char *argv[]); handle_plchangesposid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistinfo(Client &client, unsigned argc, char *argv[]); handle_playlistinfo(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistid(Client &client, unsigned argc, char *argv[]); handle_playlistid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistfind(Client &client, unsigned argc, char *argv[]); handle_playlistfind(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_playlistsearch(Client &client, unsigned argc, char *argv[]); handle_playlistsearch(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_prio(Client &client, unsigned argc, char *argv[]); handle_prio(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_prioid(Client &client, unsigned argc, char *argv[]); handle_prioid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_move(Client &client, unsigned argc, char *argv[]); handle_move(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_moveid(Client &client, unsigned argc, char *argv[]); handle_moveid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_swap(Client &client, unsigned argc, char *argv[]); handle_swap(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_swapid(Client &client, unsigned argc, char *argv[]); handle_swapid(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "Partition.hxx" #include "Partition.hxx"
#include "Instance.hxx" #include "Instance.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include <string.h> #include <string.h>
...@@ -51,20 +52,22 @@ sticker_song_find_print_cb(const LightSong &song, const char *value, ...@@ -51,20 +52,22 @@ sticker_song_find_print_cb(const LightSong &song, const char *value,
} }
static CommandResult static CommandResult
handle_sticker_song(Client &client, unsigned argc, char *argv[]) handle_sticker_song(Client &client, ConstBuffer<const char *> args)
{ {
Error error; Error error;
const Database *db = client.GetDatabase(error); const Database *db = client.GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return print_error(client, error); return print_error(client, error);
const char *const cmd = args.front();
/* get song song_id key */ /* get song song_id key */
if (argc == 5 && strcmp(argv[1], "get") == 0) { if (args.size == 4 && strcmp(cmd, "get") == 0) {
const LightSong *song = db->GetSong(argv[3], error); const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
const auto value = sticker_song_get_value(*song, argv[4]); const auto value = sticker_song_get_value(*song, args[3]);
db->ReturnSong(song); db->ReturnSong(song);
if (value.empty()) { if (value.empty()) {
command_error(client, ACK_ERROR_NO_EXIST, command_error(client, ACK_ERROR_NO_EXIST,
...@@ -72,12 +75,12 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[]) ...@@ -72,12 +75,12 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::ERROR; return CommandResult::ERROR;
} }
sticker_print_value(client, argv[4], value.c_str()); sticker_print_value(client, args[3], value.c_str());
return CommandResult::OK; return CommandResult::OK;
/* list song song_id */ /* list song song_id */
} else if (argc == 4 && strcmp(argv[1], "list") == 0) { } else if (args.size == 3 && strcmp(cmd, "list") == 0) {
const LightSong *song = db->GetSong(argv[3], error); const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
...@@ -90,12 +93,12 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[]) ...@@ -90,12 +93,12 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::OK; return CommandResult::OK;
/* set song song_id id key */ /* set song song_id id key */
} else if (argc == 6 && strcmp(argv[1], "set") == 0) { } else if (args.size == 5 && strcmp(cmd, "set") == 0) {
const LightSong *song = db->GetSong(argv[3], error); const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
bool ret = sticker_song_set_value(*song, argv[4], argv[5]); bool ret = sticker_song_set_value(*song, args[3], args[4]);
db->ReturnSong(song); db->ReturnSong(song);
if (!ret) { if (!ret) {
command_error(client, ACK_ERROR_SYSTEM, command_error(client, ACK_ERROR_SYSTEM,
...@@ -105,15 +108,15 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[]) ...@@ -105,15 +108,15 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::OK; return CommandResult::OK;
/* delete song song_id [key] */ /* delete song song_id [key] */
} else if ((argc == 4 || argc == 5) && } else if ((args.size == 3 || args.size == 4) &&
strcmp(argv[1], "delete") == 0) { strcmp(cmd, "delete") == 0) {
const LightSong *song = db->GetSong(argv[3], error); const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
bool ret = argc == 4 bool ret = args.size == 3
? sticker_song_delete(*song) ? sticker_song_delete(*song)
: sticker_song_delete_value(*song, argv[4]); : sticker_song_delete_value(*song, args[3]);
db->ReturnSong(song); db->ReturnSong(song);
if (!ret) { if (!ret) {
command_error(client, ACK_ERROR_SYSTEM, command_error(client, ACK_ERROR_SYSTEM,
...@@ -123,15 +126,15 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[]) ...@@ -123,15 +126,15 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::OK; return CommandResult::OK;
/* find song dir key */ /* find song dir key */
} else if (argc == 5 && strcmp(argv[1], "find") == 0) { } else if (args.size == 4 && strcmp(cmd, "find") == 0) {
/* "sticker find song a/directory name" */ /* "sticker find song a/directory name" */
const char *const base_uri = argv[3]; const char *const base_uri = args[2];
bool success; bool success;
struct sticker_song_find_data data = { struct sticker_song_find_data data = {
client, client,
argv[4], args[3],
}; };
success = sticker_song_find(*db, base_uri, data.name, success = sticker_song_find(*db, base_uri, data.name,
...@@ -150,9 +153,9 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[]) ...@@ -150,9 +153,9 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_sticker(Client &client, unsigned argc, char *argv[]) handle_sticker(Client &client, ConstBuffer<const char *> args)
{ {
assert(argc >= 4); assert(args.size >= 3);
if (!sticker_enabled()) { if (!sticker_enabled()) {
command_error(client, ACK_ERROR_UNKNOWN, command_error(client, ACK_ERROR_UNKNOWN,
...@@ -160,8 +163,8 @@ handle_sticker(Client &client, unsigned argc, char *argv[]) ...@@ -160,8 +163,8 @@ handle_sticker(Client &client, unsigned argc, char *argv[])
return CommandResult::ERROR; return CommandResult::ERROR;
} }
if (strcmp(argv[2], "song") == 0) if (strcmp(args[1], "song") == 0)
return handle_sticker_song(client, argc, argv); return handle_sticker_song(client, args);
else { else {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
"unknown sticker domain"); "unknown sticker domain");
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_sticker(Client &client, unsigned argc, char *argv[]); handle_sticker(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "fs/Traits.hxx" #include "fs/Traits.hxx"
#include "client/Client.hxx" #include "client/Client.hxx"
#include "Partition.hxx" #include "Partition.hxx"
...@@ -167,7 +168,7 @@ print_storage_uri(Client &client, const Storage &storage) ...@@ -167,7 +168,7 @@ print_storage_uri(Client &client, const Storage &storage)
} }
CommandResult CommandResult
handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *argv[]) handle_listmounts(Client &client, gcc_unused ConstBuffer<const char *> args)
{ {
Storage *_composite = client.partition.instance.storage; Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) { if (_composite == nullptr) {
...@@ -189,7 +190,7 @@ handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *arg ...@@ -189,7 +190,7 @@ handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *arg
} }
CommandResult CommandResult
handle_mount(Client &client, gcc_unused unsigned argc, char *argv[]) handle_mount(Client &client, ConstBuffer<const char *> args)
{ {
Storage *_composite = client.partition.instance.storage; Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) { if (_composite == nullptr) {
...@@ -199,8 +200,8 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -199,8 +200,8 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[])
CompositeStorage &composite = *(CompositeStorage *)_composite; CompositeStorage &composite = *(CompositeStorage *)_composite;
const char *const local_uri = argv[1]; const char *const local_uri = args[0];
const char *const remote_uri = argv[2]; const char *const remote_uri = args[1];
if (*local_uri == 0) { if (*local_uri == 0) {
command_error(client, ACK_ERROR_ARG, "Bad mount point"); command_error(client, ACK_ERROR_ARG, "Bad mount point");
...@@ -252,7 +253,7 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -252,7 +253,7 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[]) handle_unmount(Client &client, ConstBuffer<const char *> args)
{ {
Storage *_composite = client.partition.instance.storage; Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) { if (_composite == nullptr) {
...@@ -262,7 +263,7 @@ handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -262,7 +263,7 @@ handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[])
CompositeStorage &composite = *(CompositeStorage *)_composite; CompositeStorage &composite = *(CompositeStorage *)_composite;
const char *const local_uri = argv[1]; const char *const local_uri = args.front();
if (*local_uri == 0) { if (*local_uri == 0) {
command_error(client, ACK_ERROR_ARG, "Bad mount point"); command_error(client, ACK_ERROR_ARG, "Bad mount point");
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
class Client; class Client;
class Storage; class Storage;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_listfiles_storage(Client &client, Storage &storage, const char *uri); handle_listfiles_storage(Client &client, Storage &storage, const char *uri);
...@@ -32,12 +33,12 @@ CommandResult ...@@ -32,12 +33,12 @@ CommandResult
handle_listfiles_storage(Client &client, const char *uri); handle_listfiles_storage(Client &client, const char *uri);
CommandResult CommandResult
handle_listmounts(Client &client, unsigned argc, char *argv[]); handle_listmounts(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_mount(Client &client, unsigned argc, char *argv[]); handle_mount(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_unmount(Client &client, unsigned argc, char *argv[]); handle_unmount(Client &client, ConstBuffer<const char *> args);
#endif #endif
...@@ -25,15 +25,16 @@ ...@@ -25,15 +25,16 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "tag/Tag.hxx" #include "tag/Tag.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include "util/ConstBuffer.hxx"
CommandResult CommandResult
handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[]) handle_addtagid(Client &client, ConstBuffer<const char *> args)
{ {
unsigned song_id; unsigned song_id;
if (!check_unsigned(client, &song_id, argv[1])) if (!check_unsigned(client, &song_id, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
const char *const tag_name = argv[2]; const char *const tag_name = args[1];
const TagType tag_type = tag_name_parse_i(tag_name); const TagType tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) { if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
...@@ -41,7 +42,7 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -41,7 +42,7 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[])
return CommandResult::ERROR; return CommandResult::ERROR;
} }
const char *const value = argv[3]; const char *const value = args[2];
Error error; Error error;
if (!client.partition.playlist.AddSongIdTag(song_id, tag_type, value, if (!client.partition.playlist.AddSongIdTag(song_id, tag_type, value,
...@@ -52,15 +53,15 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[]) ...@@ -52,15 +53,15 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[])
} }
CommandResult CommandResult
handle_cleartagid(Client &client, unsigned argc, char *argv[]) handle_cleartagid(Client &client, ConstBuffer<const char *> args)
{ {
unsigned song_id; unsigned song_id;
if (!check_unsigned(client, &song_id, argv[1])) if (!check_unsigned(client, &song_id, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
TagType tag_type = TAG_NUM_OF_ITEM_TYPES; TagType tag_type = TAG_NUM_OF_ITEM_TYPES;
if (argc >= 3) { if (args.size >= 2) {
const char *const tag_name = argv[2]; const char *const tag_name = args[1];
tag_type = tag_name_parse_i(tag_name); tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) { if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
......
...@@ -23,11 +23,12 @@ ...@@ -23,11 +23,12 @@
#include "CommandResult.hxx" #include "CommandResult.hxx"
class Client; class Client;
template<typename T> struct ConstBuffer;
CommandResult CommandResult
handle_addtagid(Client &client, unsigned argc, char *argv[]); handle_addtagid(Client &client, ConstBuffer<const char *> args);
CommandResult CommandResult
handle_cleartagid(Client &client, unsigned argc, char *argv[]); handle_cleartagid(Client &client, ConstBuffer<const char *> args);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment