Skip to content

Commit

Permalink
Merge branch 'stickernames-types' of https://github.com/jcorporation/MPD
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Oct 26, 2024
2 parents 17d0cd0 + 26c4211 commit 38b46e6
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 2 deletions.
2 changes: 1 addition & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ver 0.24 (not yet released)
- show PCRE support in "config" response
- apply Unicode normalization to case-insensitive filter expressions
- stickers on playlists and some tag types
- new commands "stickernames", "stickertypes", "playlistlength", "searchplaylist"
- new commands "stickernames", "stickertypes", "stickernamestypes", "playlistlength", "searchplaylist"
- new "search"/"find" filter "added-since"
- allow range in listplaylist and listplaylistinfo
- "sticker find" supports sort and window parameter and new sticker compare operators "eq", "lt", "gt", "contains" and "starts_with"
Expand Down
3 changes: 3 additions & 0 deletions doc/protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,9 @@ Examples:
:command:`stickertypes`
Shows a list of available sticker types.

:command:`stickernamestypes [TYPE]`
Gets a list of uniq sticker names and their types.

Connection settings
===================

Expand Down
1 change: 1 addition & 0 deletions src/command/AllCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ static constexpr struct command commands[] = {
{ "sticker", PERMISSION_ADMIN, 3, -1, handle_sticker },
{ "stickernames", PERMISSION_ADMIN, 0, 0, handle_sticker_names },
{ "stickertypes", PERMISSION_ADMIN, 0, 0, handle_sticker_types },
{ "stickernamestypes", PERMISSION_ADMIN, 0, 1, handle_sticker_names_types },
#endif
{ "stop", PERMISSION_PLAYER, 0, 0, handle_stop },
{ "subscribe", PERMISSION_READ, 1, 1, handle_subscribe },
Expand Down
56 changes: 56 additions & 0 deletions src/command/StickerCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ class DomainHandler {
return CommandResult::OK;
}

CommandResult NamesTypes(const char *type) {
auto data = CallbackContext{
.name = "",
.sticker_type = sticker_type,
.response = response,
.is_song = StringIsEqual("song", sticker_type)
};

auto callback = [](const char *found_value, const char *found_type, void *user_data) {
auto context = reinterpret_cast<CallbackContext *>(user_data);
context->response.Fmt("name: {}\n", found_value);
context->response.Fmt("type: {}\n", found_type);
};

sticker_database.NamesTypes(type, callback, &data);

return CommandResult::OK;
}

protected:
DomainHandler(Response &_response,
const Database &_database,
Expand Down Expand Up @@ -334,6 +353,43 @@ handle_sticker_names(Client &client, Request args, Response &r)
return handler->Names();
}

CommandResult
handle_sticker_names_types(Client &client, Request args, Response &r)
{
auto &instance = client.GetInstance();
if (!instance.HasStickerDatabase()) {
r.Error(ACK_ERROR_UNKNOWN, "sticker database is disabled");
return CommandResult::ERROR;
}

auto &db = client.GetPartition().GetDatabaseOrThrow();
auto &sticker_database = *instance.sticker_database;

auto type = args.GetOptional(0);
std::unique_ptr<DomainHandler> handler = std::make_unique<SongHandler>(r, db, sticker_database);

if (type == nullptr ||
StringIsEqual(type, "song") ||
StringIsEqual(type, "playlist") ||
StringIsEqual(type, "filter")) {
return handler->NamesTypes(type);
}
auto tag_type = tag_name_parse(type);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
r.FmtError(ACK_ERROR_ARG, "no such tag {:?}", type);
return CommandResult::ERROR;
}
else if (sticker_allowed_tags.Test(tag_type)) {
return handler->NamesTypes(type);
}
else {
r.FmtError(ACK_ERROR_ARG, "unsupported tag {:?}", type);
return CommandResult::ERROR;
}
r.FmtError(ACK_ERROR_ARG, "unknown sticker domain {:?}", type);
return CommandResult::ERROR;
}

CommandResult
handle_sticker(Client &client, Request args, Response &r)
{
Expand Down
2 changes: 2 additions & 0 deletions src/command/StickerCommands.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ CommandResult
handle_sticker_names(Client &client, Request request, Response &response);
CommandResult
handle_sticker_types(Client &client, Request request, Response &response);
CommandResult
handle_sticker_names_types(Client &client, Request request, Response &response);

#endif
33 changes: 32 additions & 1 deletion src/sticker/Database.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ enum sticker_sql {
STICKER_SQL_TRANSACTION_COMMIT,
STICKER_SQL_TRANSACTION_ROLLBACK,
STICKER_SQL_NAMES,
STICKER_SQL_NAMES_TYPES,
STICKER_SQL_NAMES_TYPES_BY_TYPE,

STICKER_SQL_COUNT
};
Expand Down Expand Up @@ -106,7 +108,13 @@ static constexpr auto sticker_sql = std::array {
"ROLLBACK",

//[STICKER_SQL_NAMES]
"SELECT DISTINCT name FROM sticker order by name",
"SELECT DISTINCT name FROM sticker ORDER BY name",

//[STICKER_SQL_NAMES_TYPES]
"SELECT name,type FROM sticker GROUP BY name,type ORDER BY name",

//[STICKER_SQL_NAMES_TYPES_BY_TYPE]
"SELECT name,type FROM sticker WHERE type = ? GROUP BY name,type ORDER BY name",
};

static constexpr const char sticker_sql_create[] =
Expand Down Expand Up @@ -478,6 +486,29 @@ StickerDatabase::Names(void (*func)(const char *value, void *user_data), void *u
});
}

void
StickerDatabase::NamesTypes(const char *type, void (*func)(const char *value, const char *type, void *user_data), void *user_data)
{
assert(func != nullptr);

sqlite3_stmt *const s = type == nullptr
? stmt[STICKER_SQL_NAMES_TYPES]
: stmt[STICKER_SQL_NAMES_TYPES_BY_TYPE];
assert(s != nullptr);

if (type != nullptr)
BindAll(s, type);

AtScopeExit(s) {
sqlite3_reset(s);
};

ExecuteForEach(s, [s, func, user_data](){
func((const char*)sqlite3_column_text(s, 0),
(const char*)sqlite3_column_text(s, 1), user_data);
});
}

void
StickerDatabase::BatchDeleteNoIdle(const std::list<StickerTypeUriPair> &stickers)
{
Expand Down
7 changes: 7 additions & 0 deletions src/sticker/Database.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class StickerDatabase {
SQL_TRANSACTION_COMMIT,
SQL_TRANSACTION_ROLLBACK,
SQL_NAMES,
SQL_NAMES_TYPES,
SQL_NAMES_TYPES_BY_TYPE,

SQL_COUNT
};
Expand Down Expand Up @@ -166,6 +168,11 @@ public:
*/
void Names(void (*func)(const char *value, void *user_data), void *user_data);

/**
* Uniq and sorted list of all sticker names by type
*/
void NamesTypes(const char *type, void (*func)(const char *value, const char *type, void *user_data), void *user_data);

using StickerTypeUriPair = std::pair<std::string, std::string>;

/**
Expand Down

0 comments on commit 38b46e6

Please sign in to comment.