aboutsummaryrefslogtreecommitdiffstats
path: root/src/command/DatabaseCommands.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/DatabaseCommands.cxx')
-rw-r--r--src/command/DatabaseCommands.cxx168
1 files changed, 115 insertions, 53 deletions
diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx
index a7d2467b8..a3ea8d0ae 100644
--- a/src/command/DatabaseCommands.cxx
+++ b/src/command/DatabaseCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,47 +19,59 @@
#include "config.h"
#include "DatabaseCommands.hxx"
-#include "DatabaseQueue.hxx"
-#include "DatabasePlaylist.hxx"
-#include "DatabasePrint.hxx"
-#include "DatabaseSelection.hxx"
+#include "db/DatabaseGlue.hxx"
+#include "db/DatabaseQueue.hxx"
+#include "db/DatabasePlaylist.hxx"
+#include "db/DatabasePrint.hxx"
+#include "db/Count.hxx"
+#include "db/Selection.hxx"
#include "CommandError.hxx"
-#include "Client.hxx"
+#include "client/Client.hxx"
#include "tag/Tag.hxx"
-#include "util/UriUtil.hxx"
+#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "SongFilter.hxx"
#include "protocol/Result.hxx"
#include "BulkEdit.hxx"
-#include <assert.h>
#include <string.h>
CommandResult
-handle_lsinfo2(Client &client, int argc, char *argv[])
+handle_listfiles_db(Client &client, const char *uri)
{
- const char *uri;
+ const DatabaseSelection selection(uri, false);
- if (argc == 2)
- uri = argv[1];
- else
+ Error error;
+ if (!db_selection_print(client, selection, false, true, error))
+ return print_error(client, error);
+
+ return CommandResult::OK;
+}
+
+CommandResult
+handle_lsinfo2(Client &client, unsigned argc, char *argv[])
+{
+ const char *const uri = argc == 2
+ ? argv[1]
/* default is root directory */
- uri = "";
+ : "";
const DatabaseSelection selection(uri, false);
Error error;
- if (!db_selection_print(client, selection, true, error))
+ if (!db_selection_print(client, selection, true, false, error))
return print_error(client, error);
return CommandResult::OK;
}
static CommandResult
-handle_match(Client &client, int argc, char *argv[], bool fold_case)
+handle_match(Client &client, unsigned argc, char *argv[], bool fold_case)
{
+ ConstBuffer<const char *> args(argv + 1, argc - 1);
+
SongFilter filter;
- if (!filter.Parse(argc - 1, argv + 1, fold_case)) {
+ if (!filter.Parse(args, fold_case)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
@@ -67,28 +79,30 @@ handle_match(Client &client, int argc, char *argv[], bool fold_case)
const DatabaseSelection selection("", true, &filter);
Error error;
- return db_selection_print(client, selection, true, error)
+ return db_selection_print(client, selection, true, false, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_find(Client &client, int argc, char *argv[])
+handle_find(Client &client, unsigned argc, char *argv[])
{
return handle_match(client, argc, argv, false);
}
CommandResult
-handle_search(Client &client, int argc, char *argv[])
+handle_search(Client &client, unsigned argc, char *argv[])
{
return handle_match(client, argc, argv, true);
}
static CommandResult
-handle_match_add(Client &client, int argc, char *argv[], bool fold_case)
+handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case)
{
+ ConstBuffer<const char *> args(argv + 1, argc - 1);
+
SongFilter filter;
- if (!filter.Parse(argc - 1, argv + 1, fold_case)) {
+ if (!filter.Parse(args, fold_case)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
@@ -103,51 +117,73 @@ handle_match_add(Client &client, int argc, char *argv[], bool fold_case)
}
CommandResult
-handle_findadd(Client &client, int argc, char *argv[])
+handle_findadd(Client &client, unsigned argc, char *argv[])
{
return handle_match_add(client, argc, argv, false);
}
CommandResult
-handle_searchadd(Client &client, int argc, char *argv[])
+handle_searchadd(Client &client, unsigned argc, char *argv[])
{
return handle_match_add(client, argc, argv, true);
}
CommandResult
-handle_searchaddpl(Client &client, int argc, char *argv[])
+handle_searchaddpl(Client &client, unsigned argc, char *argv[])
{
- const char *playlist = argv[1];
+ ConstBuffer<const char *> args(argv + 1, argc - 1);
+ const char *playlist = args.shift();
SongFilter filter;
- if (!filter.Parse(argc - 2, argv + 2, true)) {
+ if (!filter.Parse(args, true)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
Error error;
- return search_add_to_playlist("", playlist, &filter, error)
+ const Database *db = client.GetDatabase(error);
+ if (db == nullptr)
+ return print_error(client, error);
+
+ return search_add_to_playlist(*db, *client.GetStorage(),
+ "", playlist, &filter, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_count(Client &client, int argc, char *argv[])
+handle_count(Client &client, unsigned argc, char *argv[])
{
+ ConstBuffer<const char *> args(argv + 1, argc - 1);
+
+ 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,
+ "Unknown tag type: %s", s);
+ return CommandResult::ERROR;
+ }
+
+ args.pop_back();
+ args.pop_back();
+ }
+
SongFilter filter;
- if (!filter.Parse(argc - 1, argv + 1, false)) {
+ if (!args.IsEmpty() && !filter.Parse(args, false)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
return CommandResult::ERROR;
}
Error error;
- return searchStatsForSongsIn(client, "", &filter, error)
+ return PrintSongCount(client, "", &filter, group, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_listall(Client &client, gcc_unused int argc, char *argv[])
+handle_listall(Client &client, gcc_unused unsigned argc, char *argv[])
{
const char *directory = "";
@@ -155,30 +191,31 @@ handle_listall(Client &client, gcc_unused int argc, char *argv[])
directory = argv[1];
Error error;
- return printAllIn(client, directory, error)
+ return db_selection_print(client, DatabaseSelection(directory, true),
+ false, false, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_list(Client &client, int argc, char *argv[])
+handle_list(Client &client, unsigned argc, char *argv[])
{
- unsigned tagType = locate_parse_type(argv[1]);
-
- if (tagType == TAG_NUM_OF_ITEM_TYPES) {
- command_error(client, ACK_ERROR_ARG, "\"%s\" is not known", argv[1]);
- return CommandResult::ERROR;
- }
+ ConstBuffer<const char *> args(argv + 1, argc - 1);
+ const char *tag_name = args.shift();
+ unsigned tagType = locate_parse_type(tag_name);
- if (tagType == LOCATE_TAG_ANY_TYPE) {
+ if (tagType >= TAG_NUM_OF_ITEM_TYPES &&
+ tagType != LOCATE_TAG_FILE_TYPE) {
command_error(client, ACK_ERROR_ARG,
- "\"any\" is not a valid return tag type");
+ "Unknown tag type: %s", tag_name);
return CommandResult::ERROR;
}
- /* for compatibility with < 0.12.0 */
- SongFilter *filter;
- if (argc == 3) {
+ SongFilter *filter = nullptr;
+ uint32_t group_mask = 0;
+
+ if (args.size == 1) {
+ /* for compatibility with < 0.12.0 */
if (tagType != TAG_ALBUM) {
command_error(client, ACK_ERROR_ARG,
"should be \"%s\" for 3 arguments",
@@ -186,21 +223,45 @@ handle_list(Client &client, int argc, char *argv[])
return CommandResult::ERROR;
}
- filter = new SongFilter((unsigned)TAG_ARTIST, argv[2]);
- } else if (argc > 2) {
+ filter = new SongFilter((unsigned)TAG_ARTIST, args.shift());
+ }
+
+ while (args.size >= 2 &&
+ strcmp(args[args.size - 2], "group") == 0) {
+ 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,
+ "Unknown tag type: %s", s);
+ return CommandResult::ERROR;
+ }
+
+ group_mask |= 1u << unsigned(gt);
+
+ args.pop_back();
+ args.pop_back();
+ }
+
+ if (!args.IsEmpty()) {
filter = new SongFilter();
- if (!filter->Parse(argc - 2, argv + 2, false)) {
+ if (!filter->Parse(args, false)) {
delete filter;
command_error(client, ACK_ERROR_ARG,
"not able to parse args");
return CommandResult::ERROR;
}
- } else
- filter = nullptr;
+ }
+
+ if (tagType < TAG_NUM_OF_ITEM_TYPES &&
+ group_mask & (1u << tagType)) {
+ delete filter;
+ command_error(client, ACK_ERROR_ARG, "Conflicting group");
+ return CommandResult::ERROR;
+ }
Error error;
CommandResult ret =
- listAllUniqueTags(client, tagType, filter, error)
+ PrintUniqueTags(client, tagType, group_mask, filter, error)
? CommandResult::OK
: print_error(client, error);
@@ -210,7 +271,7 @@ handle_list(Client &client, int argc, char *argv[])
}
CommandResult
-handle_listallinfo(Client &client, gcc_unused int argc, char *argv[])
+handle_listallinfo(Client &client, gcc_unused unsigned argc, char *argv[])
{
const char *directory = "";
@@ -218,7 +279,8 @@ handle_listallinfo(Client &client, gcc_unused int argc, char *argv[])
directory = argv[1];
Error error;
- return printInfoForAllIn(client, directory, error)
+ return db_selection_print(client, DatabaseSelection(directory, true),
+ true, false, error)
? CommandResult::OK
: print_error(client, error);
}