diff --git a/NEWS b/NEWS index 9f8901d..1c6b4fb 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ libmpdclient 2.24 (not yet released) +* support MPD protocol 0.25 + - stringnormalization libmpdclient 2.23 (2025/06/24) * support MPD protocol 0.24.0 diff --git a/include/mpd/client.h b/include/mpd/client.h index 0abbb84..00c7aa7 100644 --- a/include/mpd/client.h +++ b/include/mpd/client.h @@ -57,6 +57,7 @@ #include "stats.h" #include "status.h" #include "sticker.h" +#include "stringnormalization.h" /* this is a generated header and may be installed in a different filesystem tree, therefore we can't use just "version.h" */ diff --git a/include/mpd/stringnormalization.h b/include/mpd/stringnormalization.h new file mode 100644 index 0000000..d771e82 --- /dev/null +++ b/include/mpd/stringnormalization.h @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright The Music Player Daemon Project + +#ifndef LIBMPDCLIENT_STRINGNORMALIZATION_H +#define LIBMPDCLIENT_STRINGNORMALIZATION_H + +#include "recv.h" +#include "compiler.h" + +#include + +/** + * @since libmpdclient 2.24 + */ +enum mpd_stringnormalization_option +{ + /** + * Special value returned by mpd_stringnormalization_parse() when an + * unknown name was passed. + */ + MPD_STRINGNORMALIZATION_UNKNOWN = -1, + + MPD_STRINGNORMALIZATION_STRIP_DIACRITICS, + + /* IMPORTANT: the ordering above must be + retained, or else the libmpdclient ABI breaks */ + + MPD_STRINGNORMALIZATION_COUNT +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Looks up the name of the specified stringnormalization option. + * + * @return the name, or NULL if the tag type is not valid + */ +const char * +mpd_stringnormalization_name(enum mpd_stringnormalization_option option); + +/** + * Parses a stringnormalization option name, and returns its #mpd_protocol_feature value. + * + * @return a #mpd_protocol_feature value, or MPD_FEATURE_UNKNOWN if the name was + * not recognized + */ +enum mpd_stringnormalization_option +mpd_stringnormalization_name_parse(const char *name); + +/** + * Requests a list of enabled stringnormalization options. + * Use mpd_recv_stringnormalization_pair() to obtain the list of + * "option" pairs. + * + * @param connection the connection to MPD + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_list_stringnormalization(struct mpd_connection *connection); + +/** + * Requests a list of available protocol features. + * Use mpd_recv_stringnormalization_pair() to obtain the list of + * "stringnormalization option" pairs. + * + * @param connection the connection to MPD + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_list_stringnormalization_available(struct mpd_connection *connection); + +/** + * Receives the next stringnormalization option. Call this in a loop after + * mpd_send_list_stringnormalization(). + * + * Free the return value with mpd_return_pair(). + * + * @param connection a #mpd_connection + * @returns a "stringnormalization option" pair, or NULL on error or if the end of the + * response is reached + * + * @since libmpdclient 2.24, MPD 0.25 + */ +mpd_malloc +static inline struct mpd_pair * +mpd_recv_stringnormalization_pair(struct mpd_connection *connection) +{ + return mpd_recv_pair_named(connection, "stringnormalization"); +} + +/** + * Disables one or more stringnormalization option from the list of stringnormalization options. + * + * @param connection the connection to MPD + * @param options an array of stringnormalization options to disable + * @param n the number of protocol features in the array + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_disable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n); + +/** + * Shortcut for mpd_send_disable_stringnormalization() and mpd_response_finish(). + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_run_disable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n); + +/** + * Re-enable one or more stringnormalization options from the list of stringnormalization options + * for this client. + * + * @param connection the connection to MPD + * @param options an array of stringnormalization options to enable + * @param n the number of protocol features in the array + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_enable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n); + +/** + * Shortcut for mpd_send_enable_stringnormalization() and mpd_response_finish(). + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_run_enable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n); + +/** + * Clear the list of enabled stringnormalization options for this client. + * + * @param connection the connection to MPD + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_clear_stringnormalization(struct mpd_connection *connection); + +/** + * Shortcut for mpd_send_clear_stringnormalization() and mpd_response_finish(). + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_run_clear_stringnormalization(struct mpd_connection *connection); + +/** + * Enable all available stringnormalization options for this client. + * + * @param connection the connection to MPD + * @return true on success, false on error + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_send_all_stringnormalization(struct mpd_connection *connection); + +/** + * Shortcut for mpd_send_all_stringnormalization() and mpd_response_finish(). + * + * @since libmpdclient 2.24, MPD 0.25 + */ +bool +mpd_run_all_stringnormalization(struct mpd_connection *connection); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmpdclient.ld b/libmpdclient.ld index ffea1c9..4c8a5fd 100644 --- a/libmpdclient.ld +++ b/libmpdclient.ld @@ -468,6 +468,20 @@ global: mpd_lookup_consume_state; mpd_parse_consume_state; + /* mpd/stringnormalization.h */ + mpd_stringnormalization_name; + mpd_stringnormalization_name_parse; + mpd_send_list_stringnormalization; + mpd_send_list_stringnormalization_available; + mpd_send_disable_stringnormalization; + mpd_run_disable_stringnormalization; + mpd_send_enable_stringnormalization; + mpd_run_enable_stringnormalization; + mpd_send_clear_stringnormalization; + mpd_run_clear_stringnormalization; + mpd_send_all_stringnormalization; + mpd_run_all_stringnormalization; + /* mpd/tag.h */ mpd_tag_name; mpd_tag_name_parse; diff --git a/meson.build b/meson.build index 82086f1..4192a46 100644 --- a/meson.build +++ b/meson.build @@ -155,6 +155,7 @@ libmpdclient = library('mpdclient', 'src/albumart.c', 'src/readpicture.c', 'src/position.c', + 'src/stringnormalization.c', link_depends: [ 'libmpdclient.ld' ], diff --git a/src/stringnormalization.c b/src/stringnormalization.c new file mode 100644 index 0000000..857f5fa --- /dev/null +++ b/src/stringnormalization.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright The Music Player Daemon Project + +#include +#include +#include +#include +#include "internal.h" + +#include +#include +#include + +static const char *const mpd_stringnormalization_options[MPD_STRINGNORMALIZATION_COUNT] = +{ + [MPD_STRINGNORMALIZATION_STRIP_DIACRITICS] = "strip_diacritics", +}; + +const char * +mpd_stringnormalization_name(enum mpd_stringnormalization_option option) +{ + if ((unsigned)option >= MPD_STRINGNORMALIZATION_COUNT) + return NULL; + + return mpd_stringnormalization_options[option]; +} + +enum mpd_stringnormalization_option +mpd_stringnormalization_name_parse(const char *name) +{ + assert(name != NULL); + + for (unsigned i = 0; i < MPD_STRINGNORMALIZATION_COUNT; ++i) + if (strcmp(name, mpd_stringnormalization_options[i]) == 0) + return (enum mpd_stringnormalization_option)i; + + return MPD_STRINGNORMALIZATION_UNKNOWN; +} + +bool +mpd_send_list_stringnormalization(struct mpd_connection *connection) +{ + return mpd_send_command(connection, "stringnormalization", NULL); +} + +bool +mpd_send_list_stringnormalization_available(struct mpd_connection *connection) +{ + return mpd_send_command(connection, "stringnormalization", "available", NULL); +} + +static bool +mpd_send_stringnormalization_v(struct mpd_connection *connection, + const char *sub_command, + const enum mpd_stringnormalization_option *options, unsigned n) +{ + assert(connection != NULL); + assert(options != NULL); + assert(n > 0); + + if (mpd_error_is_defined(&connection->error)) + return false; + + char buffer[1024] = "stringnormalization "; + strcat(buffer, sub_command); + size_t length = strlen(buffer); + + for (unsigned i = 0; i < n; ++i) { + const char *t = mpd_stringnormalization_name(options[i]); + assert(t != NULL); + size_t t_length = strlen(t); + + if (length + 1 + t_length + 1 > sizeof(buffer)) { + mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); + mpd_error_message(&connection->error, + "Stringnormalization list is too long"); + return false; + } + + buffer[length++] = ' '; + memcpy(buffer + length, t, t_length); + length += t_length; + } + + buffer[length] = 0; + + return mpd_send_command(connection, buffer, NULL); +} + +bool +mpd_send_disable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n) +{ + return mpd_send_stringnormalization_v(connection, "disable", options, n); +} + +bool +mpd_run_disable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n) +{ + return mpd_send_disable_stringnormalization(connection, options, n) && + mpd_response_finish(connection); +} + +bool +mpd_send_enable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n) +{ + return mpd_send_stringnormalization_v(connection, "enable", options, n); +} + +bool +mpd_run_enable_stringnormalization(struct mpd_connection *connection, + const enum mpd_stringnormalization_option *options, unsigned n) +{ + return mpd_send_enable_stringnormalization(connection, options, n) && + mpd_response_finish(connection); +} + +bool +mpd_send_clear_stringnormalization(struct mpd_connection *connection) +{ + return mpd_send_command(connection, "stringnormalization", "clear", NULL); +} + +bool +mpd_run_clear_stringnormalization(struct mpd_connection *connection) +{ + return mpd_send_clear_stringnormalization(connection) && + mpd_response_finish(connection); +} + +bool +mpd_send_all_stringnormalization(struct mpd_connection *connection) +{ + return mpd_send_command(connection, "stringnormalization", "all", NULL); +} + +bool +mpd_run_all_stringnormalization(struct mpd_connection *connection) +{ + return mpd_send_all_stringnormalization(connection) && + mpd_response_finish(connection); +}