pax_global_header00006660000000000000000000000064150524205460014515gustar00rootroot0000000000000052 comment=5073329989bf52676d8c446176a1d29ed3ffccca MusicPlayerDaemon-libmpdclient-5073329/000077500000000000000000000000001505242054600177405ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/.github/000077500000000000000000000000001505242054600213005ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/.github/workflows/000077500000000000000000000000001505242054600233355ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/.github/workflows/build.yml000066400000000000000000000046161505242054600251660ustar00rootroot00000000000000--- on: workflow_dispatch: push: paths-ignore: - 'build/**' - 'doc/**' branches: - master pull_request: paths-ignore: - 'build/**' - 'doc/**' branches: - master jobs: build-linux: runs-on: ubuntu-latest steps: - id: checkout uses: actions/checkout@v5 - id: cache-ccache uses: hendrikmuhs/ccache-action@v1 with: key: linux - name: Install dependencies run: | sudo apt install -y --no-install-recommends \ meson \ check - name: Full Build uses: BSFishy/meson-build@v1.0.3 with: action: test directory: output/full setup-options: -Ddocumentation=false -Dtest=true options: --verbose - name: Mini Build uses: BSFishy/meson-build@v1.0.3 with: action: test directory: output/mini setup-options: -Ddocumentation=false -Dtest=true -Dtcp=false options: --verbose build-macos: runs-on: macos-latest steps: - id: checkout uses: actions/checkout@v5 - id: cache-ccache uses: hendrikmuhs/ccache-action@v1 with: key: macos - uses: actions/setup-python@v5 - name: Install dependencies run: | brew install \ meson ninja \ check - name: Meson Build uses: BSFishy/meson-build@v1.0.3 with: action: test directory: output setup-options: -Ddocumentation=false -Dtest=true options: --verbose build-windows: runs-on: windows-latest steps: - id: checkout uses: actions/checkout@v5 - name: Meson Build uses: BSFishy/meson-build@v1.0.3 with: action: build directory: output setup-options: -Ddocumentation=false options: --verbose meson-version: 1.3.0 build-windows-msvc: runs-on: windows-latest steps: - id: checkout uses: actions/checkout@v5 - name: Add VisualStudio command line tools into path uses: ilammy/msvc-dev-cmd@v1 - name: Meson Build uses: BSFishy/meson-build@v1.0.3 with: action: build directory: output setup-options: -Ddocumentation=false options: --verbose meson-version: 1.3.0 MusicPlayerDaemon-libmpdclient-5073329/.gitignore000066400000000000000000000000251505242054600217250ustar00rootroot00000000000000.stgit* *~ /output/ MusicPlayerDaemon-libmpdclient-5073329/AUTHORS000066400000000000000000000010511505242054600210050ustar00rootroot00000000000000libmpdclient authors ==================== libmpdclient was developed by many people, including: Max Kellermann Marc Pavot Martijn Koedam Avuton Olrich Andrzej Rybczak Roman Nuritdinov Romain Bignon Juergen Mang Former libmpdclient developers ------------------------------ J. Alexander Treuman Warren Dukes Eric Wong MusicPlayerDaemon-libmpdclient-5073329/LICENSES/000077500000000000000000000000001505242054600211455ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/LICENSES/BSD-2-Clause.txt000066400000000000000000000024101505242054600236640ustar00rootroot00000000000000Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MusicPlayerDaemon-libmpdclient-5073329/LICENSES/BSD-3-Clause.txt000066400000000000000000000027101505242054600236700ustar00rootroot00000000000000Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MusicPlayerDaemon-libmpdclient-5073329/NEWS000066400000000000000000000160231505242054600204410ustar00rootroot00000000000000libmpdclient 2.24 (2025/08/23) * fix missing "mpd_send_list_tag_types_available" in libmpdclient.ld * support MPD protocol 0.25 - stringnormalization libmpdclient 2.23 (2025/06/24) * support MPD protocol 0.24.0 - allow window for listplaylist and listplaylistinfo - command "playlistlength", "protocol", "stickertypes", "stickernamestypes", "searchplaylist" - tag "ShowMovement" - new sticker find api - new subcommands for "tagtypes": "available", "reset" * Support open end for mpd_search_add_window * format floating-point numbers with the POSIX localew libmpdclient 2.22 (2023/12/22) * drop the unmaintained Vala bindings * fix "version.h" conflicts when used as a Meson subproject * support MPD protocol 0.24.0 - command "save [create|replace|append]" libmpdclient 2.21 (2023/12/20) * meson.build: allow using as a Meson subproject * add mpd_recv_replay_gain_status() * support MPD protocol 0.24.0 - tag "Mood", "TitleSort" - "oneshot" consume state - allow range in "playlistmove" - commands "searchcount", "stickernames" - added attribute for songs - search: support constraint "added-since" libmpdclient 2.20 (2021/11/23) * support MPD protocol 0.23 - getvol - position argument for searchadd, findadd, load and playlistadd - whence argument for addid and add - range argument for playlistdelete * support MPD protocol 0.22.4 - binarylimit * support MPD protocol 0.22.0 - readpicture * support MPD protocol 0.21.0 - albumart * support tags "ComposerSort", "Ensemble", "Movement", "MovementNumber", "Location" * queue: make "priority" parameter unsigned libmpdclient 2.19 (2020/07/03) * fix off-by-one bug in MPD_HOST parser * add function mpd_lookup_replay_gain_mode() * playlist: add function mpd_run_playlist_move() * identify messages with length over the buffer limit * support MPD protocol 0.16 - replay gain * support MPD protocol 0.19 - idle events "neighbor" and "mount" * support MPD protocol 0.20 - rangeid * support MPD protocol 0.21 - command "tagtypes all" libmpdclient 2.18 (2020/01/20) * more out-of-memory checks * partition: add mpd_recv_partition() * support MPD protocol 0.21 - "oneshot" single state * support MPD protocol 0.22 - status: add mpd_status_get_partition() - commands "delpartition", "moveoutput" libmpdclient 2.17 (2019/12/04) * search: add mpd_search_add_db_songs_to_playlist() * idle: support event "partition" * support MPD protocol 0.19 - "listneighbors" * support MPD protocol 0.22 - "getfingerprint" * support tags "MPD_TAG_LABEL", "MPD_TAG_MUSICBRAINZ_WORKID", "Grouping", "Work", "Conductor" * support MPD partitions * mpd_async_set_keepalive() returns bool * mpd_connection_set_keepalive() returns bool * fix build failure on Haiku libmpdclient 2.16 (2018/10/09) * support MPD protocol 0.19 - "mount", "unmount", "listmounts" * support MPD protocol 0.17 - "load" with range * add mpd_output_get_attribute() * use UINX_MAX instead of `(unsigned)-1` to avoid undefined behavior libmpdclient 2.15 (2018/09/02) * support MPD protocol 0.21 - search: support search expressions - search: descending sort - search: support sorting by "Last-Modified" - song: audio format * support MPD protocol 0.17 - player: command "seekcur" * fix `-Wrestrict` compiler warning libmpdclient 2.14 (2018/02/11) * support MPD protocol 0.21 - command "outputset" - mpd_output_get_plugin() - receive output attributes * MSVC compatibility * improved local and abstract socket support libmpdclient 2.13 (2017/07/25) * fix build with meson > 0.38.1 * fix connect error "Operation now in progress" libmpdclient 2.12 (2017/07/21) * support MPD protocol 0.21 - support tag "OriginalDate" - command "tagtypes" plus "disable", "enable", "clear" * support MPD protocol 0.20 - support "plchanges" and "plchangesposid" with range * support MPD protocol 0.19 - commands "addtagid", "cleartagid" - command "listfiles" - grouping for "list" and "count" - tag "AlbumSort" - "seekid" with float time * use relative #include paths to avoid clashes with other libmpdclient copies * build with Meson instead of autotools libmpdclient 2.11 (2017/03/20) * fix heap corruption with mpd_connection_new_async() * add space before "window" search argument * detect getaddrinfo() at configure time * add support for ArtistSort and AlbumArtistSort tags * support MPD protocol 0.21 - audio format specifications "dsd64" etc. - the "sort" parameter for commands "find"/"search" libmpdclient 2.10 (2015/02/23) * support abstract sockets with "@" prefix * support tag "MUSICBRAINZ_RELEASETRACKID" * add TCP keepalive internal and external APIs * support MPD protocol 0.19 - status: support sample formats "float" and "dsd" - song: report duration with milliseconds precision - search: support constraint "modified-since" * support MPD protocol 0.20 - the "window" parameter for commands "find"/"search" libmpdclient 2.9 (2013/10/29) * directory: support attribute "Last-Modified" * support MPD protocol 0.18 - command "readcomments" - command "toggleoutput" - command "volume" - the "base" constraint for commands "find"/"search" libmpdclient 2.8 (2013/04/09) * song: support attribute "Prio" * queue: fix the ranged "prio" command * queue: support open ranges libmpdclient 2.7 (2012/02/04) * status: add nextsong/nextsongid support libmpdclient 2.6 (2011/10/23) * mpd/client.h: include message.h * queue: support song priorities libmpdclient 2.5 (2011/07/06) * playlist: implement the command "listplaylists" * idle: support event "sticker" * support the client-to-client protocol (MPD 0.17) libmpdclient 2.4 (2011/01/03) * configure.ac, resolver: implement flag --disable-tcp * resolver: fix IPv4/IPv6 on the loopback device * player: support the command "clearerror" * connection: add function mpd_connection_get_server_error_location() * settings: expose connection settings * iso8601, send: format string workarounds for WIN32 * Makefile.am: fix doxygen in out-of-tree build libmpdclient 2.3 (2010/05/25) * get default timeout from environment variable MPD_TIMEOUT * fix assertion failures on malformed URI * song: support attribute "Range" libmpdclient 2.2 (2010/04/25) * MixRamp support * fix the LIBMPDCLIENT_CHECK_VERSION() macro libmpdclient 2.1 (2009/12/06) * status: added mpd_status_get_elapsed_ms() * sticker: added sticker support * song: copy last_modified value in mpd_song_dup() * socket, async: use WSAGetLastError() instead of errno on WIN32 * socket: connect in non-blocking mode * socket: set the close-on-exec flag * tag: support C++ * sync: optimistic write, reduce select() calls * Makefile.am: use --version-script only with GNU ld * added library version compile-time checks libmpdclient 2.0 (2009/10/03) * complete rewrite and API redesign * shared library with a documented stable API * asynchronous API * too many minor changes to list here libmpdclient 0.13 (2007/05/28) libmpdclient 0.12.1 (2007/03/21) libmpdclient 0.12 (2006/09/22) libmpdclient 0.11.1 (2004/06/18) libmpdclient 0.11 (2004/06/17) libmpdclient 0.10 (2004/03/03) * these versions were never actually released; its sources were copied into the C/C++ clients MusicPlayerDaemon-libmpdclient-5073329/README.rst000066400000000000000000000016451505242054600214350ustar00rootroot00000000000000libmpdclient ============ libmpdclient is a C library which implements the `Music Player Daemon `__ protocol. The API documentation is generated during the build if you have doxygen. You may browse it online: http://www.musicpd.org/doc/libmpdclient/ libmpdclient is released under the revised BSD License. The full license can be found in the `LICENSES `__ directory. Installing from source ---------------------- You need: - a C99 compliant compiler (e.g. gcc) - `Meson 0.56 `__ and `Ninja `__ Run ``meson``: meson setup output Compile and install:: ninja -C output ninja -C output install Links ----- - `Home page and download `__ - `git repository `__ - `Bug tracker `__ MusicPlayerDaemon-libmpdclient-5073329/doc/000077500000000000000000000000001505242054600205055ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/doc/doxygen.conf.in000066400000000000000000000110471505242054600234410ustar00rootroot00000000000000#--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = libmpdclient PROJECT_NUMBER = @VERSION@ OUTPUT_DIRECTORY = doc FULL_PATH_NAMES = YES STRIP_FROM_PATH = @abs_top_srcdir@/include/ #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_STATIC = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = YES WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = @abs_top_srcdir@/include/mpd FILE_PATTERNS = *.h EXCLUDE_PATTERNS = compiler.h #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES # setting this to NO prevents doxygen from sorting functions alphabetically, # which would destroy their "natural" order SORT_MEMBER_DOCS = NO #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html DOCSET_FEEDNAME = "The Music Player Daemon Project" #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = mpd_pure= mpd_const= mpd_malloc= #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: YES. HAVE_DOT = @HAVE_DOT@ #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO MusicPlayerDaemon-libmpdclient-5073329/doc/meson.build000066400000000000000000000013311505242054600226450ustar00rootroot00000000000000dconf = configuration_data() dconf.set('VERSION', meson.project_version()) dconf.set('abs_top_srcdir', project_root) if find_program('dot', required: false).found() dconf.set('HAVE_DOT', 'YES') else dconf.set('HAVE_DOT', 'NO') endif doxyfile = configure_file(input: 'doxygen.conf.in', output: 'doxygen.conf', configuration: dconf) datadir = join_paths(get_option('datadir'), 'doc', 'spede') html_target = custom_target('apidocs', input: doxyfile, output: 'html', command: [doxygen, doxyfile], install: true, install_dir: docdir) MusicPlayerDaemon-libmpdclient-5073329/include/000077500000000000000000000000001505242054600213635ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/include/mpd/000077500000000000000000000000001505242054600221435ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/include/mpd/albumart.h000066400000000000000000000037161505242054600241320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_ALBUMART_H #define MPD_ALBUMART_H #include "compiler.h" #include #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sends the "albumart" command to MPD. Call mpd_recv_albumart() to * read response lines. * * @param connection a valid and connected #mpd_connection * @param uri the URI of the song * @param offset to read from * @return true on success * * @since libmpdclient 2.20, MPD 0.21 */ bool mpd_send_albumart(struct mpd_connection *connection, const char *uri, unsigned offset); /** * Receives the "albumart" response * * @param connection a valid and connected #mpd_connection * @param buffer an already allocated buffer, the size must be the same or greater than * the binary chunk size (default 8192, can be set with binarylimit command) * @param buffer_size the size of the allocated buffer * @return read size on success, -1 on failure * * @since libmpdclient 2.20, MPD 0.21 */ int mpd_recv_albumart(struct mpd_connection *connection, void *buffer, size_t buffer_size); /** * Shortcut for mpd_send_albumart(), mpd_recv_albumart() and * mpd_response_finish(). * * @param connection a valid and connected #mpd_connection * @param uri the URI of the song * @param offset to read from * @param buffer an already allocated buffer, the size must be the same or greater than * the binary chunk size (default 8192, can be set with binarylimit command) * @param buffer_size the size of the allocated buffer * @return read size on success, -1 on failure * * @since libmpdclient 2.20, MPD 0.21 */ int mpd_run_albumart(struct mpd_connection *connection, const char *uri, unsigned offset, void *buffer, size_t buffer_size); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/async.h000066400000000000000000000131521505242054600234330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief Asynchronous MPD connections * * This class provides a very basic interface to MPD connections. It * does not know much about the MPD protocol, it does not know any * specific MPD command. * * The constructor expects a socket descriptor which is already * connected to MPD. The first thing it does is read the server's * handshake code ("OK MPD 0.15.0"). */ #ifndef MPD_ASYNC_H #define MPD_ASYNC_H #include "error.h" #include "compiler.h" #include #include #include /** * Event bit mask for polling. */ enum mpd_async_event { /** ready to read from the file descriptor */ MPD_ASYNC_EVENT_READ = 1, /** ready to write to the file descriptor */ MPD_ASYNC_EVENT_WRITE = 2, /** hangup detected */ MPD_ASYNC_EVENT_HUP = 4, /** I/O error */ MPD_ASYNC_EVENT_ERROR = 8, }; /** * \struct mpd_async * * This opaque object represents an asynchronous connection to a MPD * server. Call mpd_async_new() to create a new instance. */ struct mpd_async; #ifdef __cplusplus extern "C" { #endif /** * Creates a new asynchronous MPD connection, based on a stream socket * connected with MPD. * * @param fd the socket file descriptor of the stream connection to MPD * @return a mpd_async object, or NULL on out of memory */ mpd_malloc struct mpd_async * mpd_async_new(int fd); /** * Closes the socket and frees memory. */ void mpd_async_free(struct mpd_async *async); /** * After an error has occurred, this function returns the error code. * If no error has occurred, it returns #MPD_ERROR_SUCCESS. */ mpd_pure enum mpd_error mpd_async_get_error(const struct mpd_async *async); /** * If mpd_async_get_error() returns an error code other than #MPD_ERROR_SUCCESS, * this function returns the human readable error message which caused this. * This message is optional, and may be NULL. The pointer is invalidated by * mpd_async_free(). * * For #MPD_ERROR_SERVER, the error message is encoded in UTF-8. * #MPD_ERROR_SYSTEM obtains its error message from the operating * system, and thus the locale's character set (and probably language) * is used. Keep that in mind when you print error messages. */ mpd_pure const char * mpd_async_get_error_message(const struct mpd_async *async); /** * Returns the error code from the operating system; on most operating * systems, this is the errno value. Calling this function is only * valid if mpd_async_get_error() returned #MPD_ERROR_SYSTEM. * * May be 0 if the operating system did not specify an error code. */ mpd_pure int mpd_async_get_system_error(const struct mpd_async *async); /** * Returns the file descriptor which should be polled by the caller. * Do not use the file descriptor for anything except polling! The * file descriptor never changes during the lifetime of this * #mpd_async object. */ mpd_pure int mpd_async_get_fd(const struct mpd_async *async); /** * Enables (or disables) TCP keepalives. * * Keepalives are enabled using the SO_KEEPALIVE socket option. They may be * required for long-idled connections to persist on some networks that * would otherwise terminate inactive TCP sessions. * * The default value is false. * * @param async the #mpd_async object * @param keepalive whether TCP keepalives should be enabled * @return true on success, false if setsockopt failed * * @since libmpdclient 2.10 */ bool mpd_async_set_keepalive(struct mpd_async *async, bool keepalive); /** * Returns a bit mask of events which should be polled for. */ mpd_pure enum mpd_async_event mpd_async_events(const struct mpd_async *async); /** * Call this function when poll() has returned events for this * object's file descriptor. libmpdclient will attempt to perform I/O * operations. * * @return false if the connection was closed due to an error */ bool mpd_async_io(struct mpd_async *async, enum mpd_async_event events); /** * Appends a command to the output buffer. * * @param async the connection * @param command the command name, followed by arguments, terminated by * NULL * @param args the list of 'const char *' arguments * @return true on success, false if the buffer is full or an error has * previously occurred */ bool mpd_async_send_command_v(struct mpd_async *async, const char *command, va_list args); /** * Appends a command to the output buffer. * * @param async the connection * @param command the command name, followed by arguments, terminated by * NULL. The arguments should be of type 'const char *' * @return true on success, false if the buffer is full or an error has * previously occurred */ mpd_sentinel bool mpd_async_send_command(struct mpd_async *async, const char *command, ...); /** * Receives a line from the input buffer. The result will be * null-terminated, without the newline character. The pointer is * only valid until the next async function is called. * * You can use mpd_parser_new() and mpd_parser_feed() for parsing the line. * * @param async the connection * @return a line on success, NULL otherwise */ mpd_malloc char * mpd_async_recv_line(struct mpd_async *async); /** * Copy raw data from the input buffer. This can be used to receive * binary data from MPD, such as album art. * * @param async the connection * @param dest a buffer where this function will copy the data * @param length of bytes to consume * @return the number of bytes copied to the destination buffer (may * be 0 if the input buffer was empty) * * @since libmpdclient 2.17 */ size_t mpd_async_recv_raw(struct mpd_async *async, void *dest, size_t length); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/audio_format.h000066400000000000000000000030411505242054600247630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_AUDIO_FORMAT_H #define MPD_AUDIO_FORMAT_H #include enum { /** * The sample format is unknown or unspecified. * * @since libmpdclient 2.15 */ MPD_SAMPLE_FORMAT_UNDEFINED = 0x00, /** * 32 bit floating point samples. */ MPD_SAMPLE_FORMAT_FLOAT = 0xe0, /** * DSD samples. */ MPD_SAMPLE_FORMAT_DSD = 0xe1, }; /** * This structure describes the format of a raw PCM stream. */ struct mpd_audio_format { /** * The sample rate in Hz. A better name for this attribute is * "frame rate", because technically, you have two samples per * frame in stereo sound. * * The special value 0 means "unknown or unspecified". */ uint32_t sample_rate; /** * The number of significant bits per sample. Samples are * currently always signed. Supported values are 8, 16, 24, * 32 and the special values #MPD_SAMPLE_FORMAT_FLOAT, * #MPD_SAMPLE_FORMAT_DSD, #MPD_SAMPLE_FORMAT_UNDEFINED. * * @since libmpdclient 2.10 added support for #MPD_SAMPLE_FORMAT_FLOAT and * #MPD_SAMPLE_FORMAT_DSD. */ uint8_t bits; /** * The number of channels. Only mono (1) and stereo (2) are * fully supported currently. * * The special value 0 means "unknown or unspecified". */ uint8_t channels; /** reserved for future use */ uint16_t reserved0; /** reserved for future use */ uint32_t reserved1; }; #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/binary.h000066400000000000000000000017521505242054600236050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_BINARY_H #define MPD_BINARY_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sends the "binarylimit" command to MPD. * * @param connection a valid and connected mpd_connection. * @param limit the binary chunk size limit. * @return true on success * * @since libmpdclient 2.20, MPD 0.22.4 */ bool mpd_send_binarylimit(struct mpd_connection *connection, unsigned limit); /** * Shortcut for mpd_send_binarylimit() and mpd_response_finish(). * * @param connection A valid and connected mpd_connection. * @param limit the binary chunk size limit. * @return true on success * * @since libmpdclient 2.20, MPD 0.22.4 */ bool mpd_run_binarylimit(struct mpd_connection *connection, unsigned limit); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/capabilities.h000066400000000000000000000240571505242054600247550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_CAPABILITIES_H #define MPD_CAPABILITIES_H #include "recv.h" #include "compiler.h" #include "tag.h" #include "feature.h" #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Requests a list of supported and allowed commands. Use * mpd_recv_command_pair() to obtain the list of "command" pairs. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_allowed_commands(struct mpd_connection *connection); /** * Requests a list of supported commands which are not allowed for * this connection. Use mpd_recv_command_pair() to obtain the list of * "command" pairs. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_disallowed_commands(struct mpd_connection *connection); /** * Receives the next supported command. Call this in a loop after * mpd_send_allowed_commands() or mpd_send_disallowed_commands(). * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection * @returns a "command" pair, or NULL on error or if the end of the * response is reached */ mpd_malloc static inline struct mpd_pair * mpd_recv_command_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "command"); } /** * Requests a list of supported URL handlers in the form "scheme://", * example: "http://". Use mpd_recv_url_scheme_pair() to obtain the list * of "handler" pairs. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_list_url_schemes(struct mpd_connection *connection); /** * Receives one line of the mpd_send_url_schemes() response. * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection * @returns a "handler" pair, or NULL on error or if the end of the * response is reached */ mpd_malloc static inline struct mpd_pair * mpd_recv_url_scheme_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "handler"); } /** * Requests a list of supported tag types. Use mpd_recv_tag_type_pair() * to obtain the list of "tagtype" pairs. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_list_tag_types(struct mpd_connection *connection); /** * Requests a list of available tag types. This are the tags enabled in * the configuration. Use mpd_recv_tag_type_pair() to obtain the list * of "tagtype" pairs. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_list_tag_types_available(struct mpd_connection *connection); /** * Receives the next tag type name. Call this in a loop after * mpd_send_list_tag_types(). * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection * @returns a "tagtype" pair, or NULL on error or if the end of the * response is reached */ mpd_malloc static inline struct mpd_pair * mpd_recv_tag_type_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "tagtype"); } /** * Remove one or more tags from the list of tag types the client is * interested in. These will be omitted from responses to this * client. * * @param connection the connection to MPD * @param types an array of tag types to disable * @param n the number of tag types in the array * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_send_disable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Shortcut for mpd_send_disable_tag_types() and mpd_response_finish(). * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_run_disable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Re-enable one or more tags from the list of tag types for this * client. These will no longer be hidden from responses to this * client. * * @param connection the connection to MPD * @param types an array of tag types to enable * @param n the number of tag types in the array * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_send_enable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Shortcut for mpd_send_enable_tag_types() and mpd_response_finish(). * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_run_enable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Clear the list of tag types this client is interested in. This * means that MPD will not send any tags to this client. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_send_clear_tag_types(struct mpd_connection *connection); /** * Shortcut for mpd_send_clear_tag_types() and mpd_response_finish(). * * @since libmpdclient 2.12, MPD 0.21 */ bool mpd_run_clear_tag_types(struct mpd_connection *connection); /** * Add all tags to the list of tag types this client is interested in. * This means that MPD will send all tags to this client. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.19, MPD 0.21 */ bool mpd_send_all_tag_types(struct mpd_connection *connection); /** * Shortcut for mpd_send_all_tag_types() and mpd_response_finish(). * * @since libmpdclient 2.19, MPD 0.21 */ bool mpd_run_all_tag_types(struct mpd_connection *connection); /** * Clear the list of tag types and re-enable one or more tags from * the list of tag types for this client. These will no longer be * hidden from responses to this client. * * @param connection the connection to MPD * @param types an array of tag types to enable * @param n the number of tag types in the array * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_reset_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Shortcut for mpd_send_reset_tag_types() and mpd_response_finish(). * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_reset_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n); /** * Requests a list of enabled protocol features. * Use mpd_recv_protocol_feature_pair() to obtain the list of * "protocol feature" pairs. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_list_protocol_features(struct mpd_connection *connection); /** * Requests a list of available protocol features. * Use mpd_recv_protocol_feature_pair() to obtain the list of * "protocol feature" pairs. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_list_protocol_features_available(struct mpd_connection *connection); /** * Receives the next protocol feature name. Call this in a loop after * mpd_send_list_protocol(). * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection * @returns a "protocol feature" pair, or NULL on error or if the end of the * response is reached * * @since libmpdclient 2.23, MPD 0.24 */ mpd_malloc static inline struct mpd_pair * mpd_recv_protocol_feature_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "feature"); } /** * Disables one or more features from the list of protocol features. * * @param connection the connection to MPD * @param features an array of protocol features to disable * @param n the number of protocol features in the array * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_disable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n); /** * Shortcut for mpd_send_disable_protocol_features() and mpd_response_finish(). * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_disable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n); /** * Re-enable one or more features from the list of protocol features * for this client. * * @param connection the connection to MPD * @param features an array of protocol features to enable * @param n the number of protocol features in the array * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_enable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n); /** * Shortcut for mpd_send_enable_protocol_features() and mpd_response_finish(). * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_enable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n); /** * Clear the list of enabled protocol features for this client. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_clear_protocol_features(struct mpd_connection *connection); /** * Shortcut for mpd_send_clear_protocol_features() and mpd_response_finish(). * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_clear_protocol_features(struct mpd_connection *connection); /** * Enable all available features for this client. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_all_protocol_features(struct mpd_connection *connection); /** * Shortcut for mpd_send_all_protocol_features() and mpd_response_finish(). * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_all_protocol_features(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/client.h000066400000000000000000000030761505242054600236000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /** * @mainpage * * This is a client library for the [Music Player * Daemon](https://www.musicpd.org/), written in C. * * You can choose one of several APIs, depending on your requirements: * * - struct mpd_async: a very low-level asynchronous API which knows * the protocol syntax, but no specific commands * * - struct mpd_connection: a basic synchronous API which knows all * MPD commands and parses all responses * * \author Max Kellermann (max.kellermann@gmail.com) */ #ifndef MPD_CLIENT_H #define MPD_CLIENT_H // IWYU pragma: begin_exports #include "audio_format.h" #include "albumart.h" #include "binary.h" #include "capabilities.h" #include "connection.h" #include "database.h" #include "directory.h" #include "entity.h" #include "feature.h" #include "fingerprint.h" #include "idle.h" #include "list.h" #include "message.h" #include "mixer.h" #include "mount.h" #include "neighbor.h" #include "output.h" #include "pair.h" #include "partition.h" #include "password.h" #include "player.h" #include "playlist.h" #include "queue.h" #include "readpicture.h" #include "recv.h" #include "replay_gain.h" #include "response.h" #include "search.h" #include "send.h" #include "settings.h" #include "song.h" #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" */ #include // IWYU pragma: end_exports #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/compiler.h000066400000000000000000000016311505242054600241270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief Compiler specific definitions * * This file is not part of the official libmpdclient2 API. It * provides access to gcc specific extensions. * */ #ifndef MPD_COMPILER_H #define MPD_COMPILER_H #if !defined(SPARSE) && defined(__GNUC__) && __GNUC__ >= 3 /* GCC 4.x */ #define mpd_unused __attribute__((unused)) #define mpd_malloc __attribute__((malloc)) #define mpd_pure __attribute__((pure)) #define mpd_const __attribute__((const)) #define mpd_sentinel __attribute__((sentinel)) #ifdef __clang__ #define mpd_printf(a,b) __attribute__((format(printf, a, b))) #else #define mpd_printf(a,b) __attribute__((format(gnu_printf, a, b))) #endif #else /* generic C compiler */ #define mpd_unused #define mpd_malloc #define mpd_pure #define mpd_const #define mpd_sentinel #define mpd_printf(a,b) #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/connection.h000066400000000000000000000222721505242054600244600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_CONNECTION_H #define MPD_CONNECTION_H #include "protocol.h" #include "error.h" #include "compiler.h" #include struct mpd_async; /** * \struct mpd_connection * * This opaque object represents a connection to a MPD server. Call * mpd_connection_new() to create a new instance. To free an * instance, call mpd_connection_free(). Example: * * struct mpd_connection *conn = mpd_connection_new(NULL, 0, 0); * * // error handling * if (conn == NULL) { * fprintf(stderr, "Out of memory\n"); * return; * } * if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { * fprintf(stderr, "%s\n", mpd_connection_get_error_message(c)); * mpd_connection_free(c); * return; * } * * // we can now use the connection * mpd_run_next(conn); * * // close the connection and free memory * mpd_connection_free(conn); * * Error handling: most functions return a `bool` indicating success * or failure. In this case, you may query the nature of the error * with the functions mpd_connection_get_error(), * mpd_connection_get_error_message(), * mpd_connection_get_server_error(). * * Some errors can be cleared by calling mpd_connection_clear_error(), * like #MPD_ERROR_SERVER, #MPD_ERROR_ARGUMENT. Most others are * fatal, and cannot be recovered, like #MPD_ERROR_CLOSED - * mpd_connection_clear_error() returns false. * * Some functions like mpd_recv_pair() cannot differentiate between * "end of response" and "error". If this function returns `NULL`, you * have to check mpd_connection_get_error(). * * To integrate this object in a non-blocking event I/O loop, use * mpd_connection_get_fd() to obtain the underlying socket descriptor. */ struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Opens a new connection to a MPD server. Both the name server * lookup and the `connect()` call are done synchronously. After this * function has returned, you should check if the connection was * successful with mpd_connection_get_error(). * * @param host the server's host name, IP address or Unix socket path. * If the resolver returns more than one IP address for a host name, * this functions tries all of them until one accepts the connection. * `NULL` is allowed here, which will connect to the default host * (using the `MPD_HOST` environment variable if present). * @param port the TCP port to connect to, 0 for default port (using * the `MPD_PORT` environment variable if present). If "host" is a Unix * socket path, this parameter is ignored. * @param timeout_ms the timeout in milliseconds, 0 for the default * timeout (the environment variable `MPD_TIMEOUT` may specify a timeout * in seconds); you may modify it later with * mpd_connection_set_timeout() * @return a mpd_connection object (which may have failed to connect), * or `NULL` on out-of-memory * * @since libmpdclient 2.3 added support for `MPD_HOST`, `MPD_PORT` * and `MPD_TIMEOUT`. */ mpd_malloc struct mpd_connection * mpd_connection_new(const char *host, unsigned port, unsigned timeout_ms); /** * Creates a #mpd_connection object based on an existing asynchronous * MPD connection. You should not continue to use the #mpd_async * object. Note that mpd_connection_free() also frees your #mpd_async * object! * * This function does not block at all, which is why you have to pass * the welcome message to it. * * @param async a #mpd_async instance * @param welcome the first line sent by MPD (the welcome message) * @return a mpd_connection object, or `NULL` on out-of-memory */ mpd_malloc struct mpd_connection * mpd_connection_new_async(struct mpd_async *async, const char *welcome); /** * Close the connection and free all memory. * * @param connection the connection to MPD */ void mpd_connection_free(struct mpd_connection *connection); /** * Returns the settings which were used to connect to the server. May * be `NULL` if the settings are not known. * * @since libmpdclient 2.4 */ const struct mpd_settings * mpd_connection_get_settings(const struct mpd_connection *connection); /** * Enables (or disables) TCP keepalives. * * Keepalives are enabled using the SO_KEEPALIVE socket option. They may be * required for long-idled connections to persist on some networks that * would otherwise terminate inactive TCP sessions. * * The default value is false. * * @param connection the connection to MPD * @param keepalive whether TCP keepalives should be enabled * @return true on success, false if setsockopt failed * * @since libmpdclient 2.10 */ bool mpd_connection_set_keepalive(struct mpd_connection *connection, bool keepalive); /** * Sets the timeout for synchronous operations. If the MPD server * does not send a response during this time span, the operation is * aborted by libmpdclient. * * The initial value is the one passed to mpd_connection_new(). If * you have used mpd_connection_new_async(), then the default value is * 30 seconds. * * @param connection the connection to MPD * @param timeout_ms the desired timeout in milliseconds; must not be 0 */ void mpd_connection_set_timeout(struct mpd_connection *connection, unsigned timeout_ms); /** * Returns the file descriptor which should be polled by the caller. * Do not use the file descriptor for anything except polling! The * file descriptor never changes during the lifetime of this * #mpd_connection object. * * To integrate this library in a non-blocking event I/O loop, use * this function to obtain the underlying socket descriptor and * register it in the event loop. As soon as it becomes ready for * reading, use this library's functions to receive responses from * MPD. Example: * * if (!mpd_send_idle(conn)) * return handle_error(); * register_socket(mpd_connection_get_fd(conn)); * * And in the event callback: * * enum mpd_idle events = mpd_recv_idle(conn); * // handle the events * // .. and then call mpd_send_idle() again to keep listening */ mpd_pure int mpd_connection_get_fd(const struct mpd_connection *connection); /** * Returns the underlying #mpd_async object. This can be used to send * commands asynchronously. During an asynchronous command, you must * not use synchronous #mpd_connection functions until the * asynchronous response has been finished. * * If an error occurs while using #mpd_async, you must close the * #mpd_connection. */ mpd_pure struct mpd_async * mpd_connection_get_async(struct mpd_connection *connection); /** * Returns the libmpdclient error code. MPD_ERROR_SUCCESS means no * error occurred. */ mpd_pure enum mpd_error mpd_connection_get_error(const struct mpd_connection *connection); /** * Returns the human-readable (English) libmpdclient error message. * Calling this function is only valid if an error really occurred. * Check with mpd_connection_get_error(). * * For #MPD_ERROR_SERVER, the error message is encoded in UTF-8. * #MPD_ERROR_SYSTEM obtains its error message from the operating * system, and thus the locale's character set (and probably language) * is used. Keep that in mind when you print error messages. */ mpd_pure const char * mpd_connection_get_error_message(const struct mpd_connection *connection); /** * Returns the error code returned from the server. Calling this * function is only valid if mpd_connection_get_error() returned * #MPD_ERROR_SERVER. */ mpd_pure enum mpd_server_error mpd_connection_get_server_error(const struct mpd_connection *connection); /** * Returns the location of the server error, i.e. an index within the * command list. Calling this function is only valid in a command * list response, and if mpd_connection_get_error() returned * #MPD_ERROR_SERVER. * * @since libmpdclient 2.4 */ mpd_pure unsigned mpd_connection_get_server_error_location(const struct mpd_connection *connection); /** * Returns the error code from the operating system; on most operating * systems, this is the errno value. Calling this function is only * valid if mpd_connection_get_error() returned #MPD_ERROR_SYSTEM. * * May be 0 if the operating system did not specify an error code. */ mpd_pure int mpd_connection_get_system_error(const struct mpd_connection *connection); /** * Attempts to recover from an error condition. This function must be * called after a non-fatal error before you can continue using this * object. * * @return true on success, false if the error is fatal and cannot be * recovered */ bool mpd_connection_clear_error(struct mpd_connection *connection); /** * Returns a three-tuple containing the major, minor and patch version * of the MPD protocol. */ mpd_pure const unsigned * mpd_connection_get_server_version(const struct mpd_connection *connection); /** * Compares the MPD protocol version with the specified triple. * * @return -1 if the server is older, 1 if it is newer, 0 if it is * equal */ mpd_pure int mpd_connection_cmp_server_version(const struct mpd_connection *connection, unsigned major, unsigned minor, unsigned patch); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/database.h000066400000000000000000000105631505242054600240650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief Database * * This file declares functions which query or update MPD's music * database. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_DATABASE_H #define MPD_DATABASE_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Get a recursive list of all directories, songs and playlist from * MPD. They are returned without metadata. This is a rather * expensive operation, because the response may be large. * * To read the response, you may use mpd_recv_entity(). * * @param connection the connection to MPD * @param path an optional base path for the query * @return true on success, false on error */ bool mpd_send_list_all(struct mpd_connection *connection, const char *path); /** * Like #mpd_send_list_all(), but return metadata. This operation is * even more expensive, because the response is larger. If it is * larger than a configurable server-side limit, MPD may disconnect * you. * * To read the response, you may use mpd_recv_entity(). * * @param connection the connection to MPD * @param path an optional base path for the query * @return true on success, false on error */ bool mpd_send_list_all_meta(struct mpd_connection *connection, const char *path); /** * Get a list of all directories, songs and playlist in a directory * from MPD, including metadata. * * To read the response, you may use mpd_recv_entity(). * * @param connection the connection to MPD * @param path an optional directory to be listed * @return true on success, false on error */ bool mpd_send_list_meta(struct mpd_connection *connection, const char *path); /** * Lists the contents of the specified directory, including files that are * not recognized by MPD (command "listfiles"). * * To read the response, you may use mpd_recv_entity(). All regular * files will be reported as #MPD_ENTITY_TYPE_SONG, even if they are * not actually songs. * * @param connection the connection to MPD * @param uri the directory to be listed * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_send_list_files(struct mpd_connection *connection, const char *uri); /** * Send "readcomments". Read the "comments" of a song file. This * returns key/value pairs which can be read using mpd_recv_pair(). * * @param connection the connection to MPD * @param path the relative path of the song file within the music * directory or an arbitrary file path starting with file:/// * @return true on success, false on error * * @since libmpdclient 2.9 */ bool mpd_send_read_comments(struct mpd_connection *connection, const char *path); /** * Instructs MPD to update the music database: find new files, remove * deleted files, update modified files. * * @param connection the connection to MPD * @param path optional path to update; if NULL, then all of the music * directory is updated * @return true on success, false on error */ bool mpd_send_update(struct mpd_connection *connection, const char *path); /** * Like mpd_send_update(), but also rescans unmodified files. * * @param connection the connection to MPD * @param path optional path to update; if NULL, then all of the music * directory is updated * @return true on success, false on error */ bool mpd_send_rescan(struct mpd_connection *connection, const char *path); /** * Receives the id of the update job which was submitted by * mpd_send_update(). * * @param connection the connection to MPD * @return a positive job id on success, 0 on error */ unsigned mpd_recv_update_id(struct mpd_connection *connection); /** * Shortcut for mpd_send_update() and mpd_recv_update_id(). * * @param connection the connection to MPD * @param path optional path to update; if NULL, then all of the music * directory is updated * @return a positive job id on success, 0 on error */ unsigned mpd_run_update(struct mpd_connection *connection, const char *path); /** * Like mpd_run_update(), but also rescans unmodified files. * * @param connection the connection to MPD * @param path optional path to update; if NULL, then all of the music * directory is updated * @return a positive job id on success, 0 on error */ unsigned mpd_run_rescan(struct mpd_connection *connection, const char *path); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/directory.h000066400000000000000000000043161505242054600243240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_DIRECTORY_H #define MPD_DIRECTORY_H #include "compiler.h" #include #include struct mpd_pair; struct mpd_connection; /** * \struct mpd_directory * * An opaque directory object. This is a container for more songs, * directories or playlists. */ struct mpd_directory; #ifdef __cplusplus extern "C" { #endif /** * Duplicates a #mpd_directory object. * * @return the new object, or NULL on out of memory */ mpd_malloc struct mpd_directory * mpd_directory_dup(const struct mpd_directory *directory); /** * Free memory allocated by the #mpd_directory object. */ void mpd_directory_free(struct mpd_directory *directory); /** * Returns the path of this directory, relative to the MPD music * directory. It does not begin with a slash. */ mpd_pure const char * mpd_directory_get_path(const struct mpd_directory *directory); /** * @return the POSIX UTC time stamp of the last modification, or 0 if * that is unknown * * @since libmpdclient 2.9 */ mpd_pure time_t mpd_directory_get_last_modified(const struct mpd_directory *directory); /** * Begins parsing a new directory. * * @param pair the first pair in this directory (name must be "directory") * @return the new #mpd_entity object, or NULL on error (out of * memory, or pair name is not "directory") */ mpd_malloc struct mpd_directory * mpd_directory_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_directory object. * * @return true if the pair was parsed and added to the directory (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next directory */ bool mpd_directory_feed(struct mpd_directory *directory, const struct mpd_pair *pair); /** * Receives the next directory from the MPD server. * * @return a #mpd_directory object, or NULL on error or if the directory list is * finished */ mpd_malloc struct mpd_directory * mpd_recv_directory(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/entity.h000066400000000000000000000060121505242054600236270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_ENTITY_H #define MPD_ENTITY_H #include "song.h" #include "directory.h" #include "compiler.h" struct mpd_pair; /** * The type of a #mpd_entity object. */ enum mpd_entity_type { /** * The type of the entity received from MPD is not implemented * in this version of libmpdclient. */ MPD_ENTITY_TYPE_UNKNOWN, /** * A directory (#mpd_directory) containing more entities. */ MPD_ENTITY_TYPE_DIRECTORY, /** * A song file (#mpd_song) which can be added to the playlist. */ MPD_ENTITY_TYPE_SONG, /** * A stored playlist (#mpd_playlist). */ MPD_ENTITY_TYPE_PLAYLIST, }; /** * \struct mpd_entity * * An "entity" is an object returned by commands like "lsinfo". It is * an object wrapping all possible entity types. */ struct mpd_entity; #ifdef __cplusplus extern "C" { #endif /** * Releases an entity. This also frees the wrapped object. */ void mpd_entity_free(struct mpd_entity *entity); /** * @return the type of this entity. */ mpd_pure enum mpd_entity_type mpd_entity_get_type(const struct mpd_entity *entity); /** * Obtains a pointer to the #mpd_directory object enclosed by this * #mpd_entity. Calling this function is only allowed if * mpd_entity_get_type() has returned #MPD_ENTITY_TYPE_DIRECTORY. * * @return the directory object */ mpd_pure const struct mpd_directory * mpd_entity_get_directory(const struct mpd_entity *entity); /** * Obtains a pointer to the #mpd_song object enclosed by this * #mpd_entity. Calling this function is only allowed if * mpd_entity_get_type() has returned #MPD_ENTITY_TYPE_SONG. * * @return the song object */ mpd_pure const struct mpd_song * mpd_entity_get_song(const struct mpd_entity *entity); /** * Obtains a pointer to the #mpd_playlist object enclosed by * this #mpd_entity. Calling this function is only allowed if * mpd_entity_get_type() has returned #MPD_ENTITY_TYPE_PLAYLIST. * * @return the playlist object */ mpd_pure const struct mpd_playlist * mpd_entity_get_playlist(const struct mpd_entity *entity); /** * Begins parsing a new entity. * * @param pair the first pair in this entity * @return the new #mpd_entity object, or NULL on error (out of memory) */ mpd_malloc struct mpd_entity * mpd_entity_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_entity object. * * @return true if the pair was parsed and added to the entity (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next entity */ bool mpd_entity_feed(struct mpd_entity *entity, const struct mpd_pair *pair); /** * Receives the next entity from the MPD server. * * @return an entity object, or NULL on error or if the entity list is * finished */ mpd_malloc struct mpd_entity * mpd_recv_entity(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/error.h000066400000000000000000000017261505242054600234530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h or * mpd/async.h instead. */ #ifndef MPD_ERROR_H #define MPD_ERROR_H enum mpd_error { /** no error */ MPD_ERROR_SUCCESS = 0, /** out of memory */ MPD_ERROR_OOM, /** a function was called with an unrecognized or invalid argument */ MPD_ERROR_ARGUMENT, /** a function was called which is not available in the current state of libmpdclient */ MPD_ERROR_STATE, /** timeout trying to talk to mpd */ MPD_ERROR_TIMEOUT, /** system error */ MPD_ERROR_SYSTEM, /** unknown host */ MPD_ERROR_RESOLVER, /** malformed response received from MPD */ MPD_ERROR_MALFORMED, /** connection closed by mpd */ MPD_ERROR_CLOSED, /** * The server has returned an error code, which can be queried * with mpd_connection_get_server_error(). */ MPD_ERROR_SERVER, }; #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/feature.h000066400000000000000000000020751505242054600237530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #ifndef LIBMPDCLIENT_FEATURE_H #define LIBMPDCLIENT_FEATURE_H /** * @since libmpdclient 2.23 */ enum mpd_protocol_feature { /** * Special value returned by mpd_feature_parse() when an * unknown name was passed. */ MPD_FEATURE_UNKNOWN = -1, MPD_FEATURE_HIDE_PLAYLISTS_IN_ROOT, /* IMPORTANT: the ordering above must be retained, or else the libmpdclient ABI breaks */ MPD_FEATURE_COUNT }; #ifdef __cplusplus extern "C" { #endif /** * Looks up the name of the specified protocol feature. * * @since libmpdclient 2.23 * * @return the name, or NULL if the tag type is not valid */ const char * mpd_feature_name(enum mpd_protocol_feature feature); /** * Parses a protocol feature name, and returns its #mpd_protocol_feature value. * * @since libmpdclient 2.23 * * @return a #mpd_protocol_feature value, or MPD_FEATURE_UNKNOWN if the name was * not recognized */ enum mpd_protocol_feature mpd_feature_name_parse(const char *name); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/fingerprint.h000066400000000000000000000035731505242054600246530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_FINGERPRINT_H #define MPD_FINGERPRINT_H #include "compiler.h" #include #include struct mpd_connection; struct mpd_pair; enum mpd_fingerprint_type { MPD_FINGERPRINT_TYPE_UNKNOWN, MPD_FINGERPRINT_TYPE_CHROMAPRINT, }; #ifdef __cplusplus extern "C" { #endif /** * Parse a #mpd_pair name to check which fingerprint type it contains. */ mpd_pure enum mpd_fingerprint_type mpd_parse_fingerprint_type(const char *name); /** * Sends the "getfingerprint" command to MPD. Call mpd_recv_pair() to * read response lines. Use mpd_parse_fingerprint_type() to check * each pair's name; the pair's value then contains the actual * fingerprint. * * @param connection a valid and connected #mpd_connection * @param uri the song URI * @return true on success * * @since libmpdclient 2.17, MPD 0.22 */ bool mpd_send_getfingerprint(struct mpd_connection *connection, const char *uri); /** * Shortcut for mpd_send_getfingerprint(), mpd_recv_pair_named() and * mpd_response_finish(). * * @param connection a valid and connected #mpd_connection * @param uri the song URI * @param buffer a buffer for the fingerprint string * @param buffer_size the size of the buffer (with enough room for a * trailing null byte); if the buffer is too small, behavior is * undefined; the library may truncate the string or fail * @return a pointer to the buffer on success or NULL on error (or if * there was no chromaprint in MPD's response) * * @since libmpdclient 2.17, MPD 0.22 */ mpd_malloc const char * mpd_run_getfingerprint_chromaprint(struct mpd_connection *connection, const char *uri, char *buffer, size_t buffer_size); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/idle.h000066400000000000000000000116151505242054600232350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_IDLE_H #define MPD_IDLE_H #include "compiler.h" #include struct mpd_pair; struct mpd_connection; /** * This enum contains bit masks for all idle events. * * @since libmpdclient 2.5 added support for #MPD_IDLE_STICKER, * #MPD_IDLE_SUBSCRIPTION and #MPD_IDLE_MESSAGE. * @since libmpdclient 2.17 added support for #MPD_IDLE_PARTITION. * @since libmpdclient 2.19 added support for #MPD_IDLE_NEIGHBOR, * #MPD_IDLE_MOUNT */ enum mpd_idle { /** song database has been updated */ MPD_IDLE_DATABASE = 0x1, /** a stored playlist has been modified, created, deleted or renamed */ MPD_IDLE_STORED_PLAYLIST = 0x2, /** the queue has been modified */ MPD_IDLE_QUEUE = 0x4, /** deprecated, don't use */ MPD_IDLE_PLAYLIST = MPD_IDLE_QUEUE, /** the player state has changed: play, stop, pause, seek, ... */ MPD_IDLE_PLAYER = 0x8, /** the volume has been modified */ MPD_IDLE_MIXER = 0x10, /** an audio output device has been enabled or disabled */ MPD_IDLE_OUTPUT = 0x20, /** options have changed: crossfade, random, repeat, ... */ MPD_IDLE_OPTIONS = 0x40, /** a database update has started or finished. */ MPD_IDLE_UPDATE = 0x80, /** a sticker has been modified. */ MPD_IDLE_STICKER = 0x100, /** a client has subscribed to or unsubscribed from a channel */ MPD_IDLE_SUBSCRIPTION = 0x200, /** a message on a subscribed channel was received */ MPD_IDLE_MESSAGE = 0x400, /** a partition was added or changed */ MPD_IDLE_PARTITION = 0x800, /** a neighbor was found or lost */ MPD_IDLE_NEIGHBOR = 0x1000, /** the mount list has changed */ MPD_IDLE_MOUNT = 0x2000, }; #ifdef __cplusplus extern "C" { #endif /** * Returns the name of the specified idle event. * * @param idle an idle event id * @return the name, or NULL if that event is not known */ mpd_const const char * mpd_idle_name(enum mpd_idle idle); /** * Parses the name of an idle event. * * @param name an idle event name * @return the id, or 0 if that event is not known */ mpd_pure enum mpd_idle mpd_idle_name_parse(const char *name); /** * Enters "idle" mode: MPD will stall the response until an event has * occurred. Call mpd_send_noidle() to abort the idle mode, or * mpd_recv_idle() to read the event mask (or synchronously wait for * events). * * @param connection the connection to MPD * @return true on success */ bool mpd_send_idle(struct mpd_connection *connection); /** * Same as mpd_send_idle(), but listen only on specific events. * * @param connection the connection to MPD * @param mask a bit mask of idle events; must not be 0 * @return true on success */ bool mpd_send_idle_mask(struct mpd_connection *connection, enum mpd_idle mask); /** * Tells MPD to leave the "idle" mode. MPD will then respond with a * list of events which have occurred (which may be empty). Call * mpd_recv_idle() after that. * * @param connection the connection to MPD * @return true on success */ bool mpd_send_noidle(struct mpd_connection *connection); /** * Parses a "changed" pair, which is part of MPD's response to the * "idle" command. * * @param pair the "changed" pair * @return an idle code, or 0 if the pair was not understood */ mpd_pure enum mpd_idle mpd_idle_parse_pair(const struct mpd_pair *pair); /** * Waits until MPD sends the list of idle events and returns it in a * bit mask. * * @param connection the connection to MPD * @param disable_timeout if true, then libmpdclient temporarily * disables the configured timeout (see mpd_connection_set_timeout()): * this function blocks forever, until either MPD sends a response, or * an error occurs. * @return the event bit mask, or 0 on error or if there were no * events */ enum mpd_idle mpd_recv_idle(struct mpd_connection *connection, bool disable_timeout); /** * Shortcut for mpd_send_idle() and mpd_recv_idle(). During * mpd_recv_idle(), the configured timeout is disabled. * * @param connection the connection to MPD * @return the event bit mask, or 0 on error */ enum mpd_idle mpd_run_idle(struct mpd_connection *connection); /** * Shortcut for mpd_send_idle_mask() and mpd_recv_idle(). During * mpd_recv_idle(), the configured timeout is disabled. * * @param connection the connection to MPD * @param mask a bit mask of idle events; must not be 0 * @return the event bit mask, or 0 on error */ enum mpd_idle mpd_run_idle_mask(struct mpd_connection *connection, enum mpd_idle mask); /** * Shortcut for mpd_send_noidle() and mpd_recv_idle(). During * mpd_recv_idle(), the configured timeout is not disabled. * * @param connection the connection to MPD * @return the event bit mask, or 0 on error or if there were no * events */ enum mpd_idle mpd_run_noidle(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/list.h000066400000000000000000000023351505242054600232720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Functions for sending command lists. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_LIST_H #define MPD_LIST_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Starts a command list, i.e. a group of pipelined commands which are * transferred in one block. If one command fails, the rest of the * command list is canceled. * * Note that there is no guarantee on atomicity. * * @param connection the connection to MPD * @param discrete_ok tells MPD whether to acknowledge every list * command with an "list_OK" response * @return true on success */ bool mpd_command_list_begin(struct mpd_connection *connection, bool discrete_ok); /** * Commits the command list, i.e. makes MPD execute all commands which * were queued. * * Note: there is no way to cancel a command list once it is started. * You may however close the socket connection. * * @param connection the connection to MPD * @return true on success */ bool mpd_command_list_end(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/meson.build000066400000000000000000000021231505242054600243030ustar00rootroot00000000000000version_conf = configuration_data() version_conf.set('MAJOR_VERSION', splitted_version[0]) version_conf.set('MINOR_VERSION', splitted_version[1]) if splitted_version.length() >= 3 version_conf.set('PATCH_VERSION', splitted_version[2]) else version_conf.set('PATCH_VERSION', '0') endif version_h = configure_file(input: 'version.h.in', output: 'version.h', configuration: version_conf) install_headers( 'async.h', 'audio_format.h', 'client.h', 'capabilities.h', 'compiler.h', 'connection.h', 'database.h', 'directory.h', 'entity.h', 'error.h', 'feature.h', 'fingerprint.h', 'idle.h', 'list.h', 'mixer.h', 'mount.h', 'neighbor.h', 'parser.h', 'partition.h', 'password.h', 'player.h', 'playlist.h', 'position.h', 'protocol.h', 'queue.h', 'recv.h', 'replay_gain.h', 'response.h', 'send.h', 'status.h', 'stats.h', 'tag.h', 'output.h', 'pair.h', 'search.h', 'socket.h', 'song.h', 'sticker.h', 'settings.h', 'message.h', 'binary.h', 'albumart.h', 'readpicture.h', 'stringnormalization.h', version_h, subdir: 'mpd', ) MusicPlayerDaemon-libmpdclient-5073329/include/mpd/message.h000066400000000000000000000112221505242054600237360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_MESSAGE_H #define MPD_MESSAGE_H #include "recv.h" #include "compiler.h" #include struct mpd_pair; /** * \struct mpd_message */ struct mpd_message; struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Begins parsing a new message. * * @param pair the first pair in this message (name must be "channel") * @return the new #mpd_entity object, or NULL on error (out of * memory, or pair name is not "channel") * * @since libmpdclient 2.5 */ mpd_malloc struct mpd_message * mpd_message_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_message object. * * @return true if the pair was parsed and added to the message (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next message * * @since libmpdclient 2.5 */ bool mpd_message_feed(struct mpd_message *output, const struct mpd_pair *pair); /** * Frees a #mpd_message object. * * @since libmpdclient 2.5 */ void mpd_message_free(struct mpd_message *message); /** * Returns the channel name. * * @since libmpdclient 2.5 */ mpd_pure const char * mpd_message_get_channel(const struct mpd_message *message); /** * Returns the message text. * * @since libmpdclient 2.5 */ mpd_pure const char * mpd_message_get_text(const struct mpd_message *message); /** * Sends the "subscribe" command: subscribe to a message channel. * * @param connection the connection to MPD * @param channel the channel name * @return true on success * * @since libmpdclient 2.5 */ bool mpd_send_subscribe(struct mpd_connection *connection, const char *channel); /** * Shortcut for mpd_send_subscribe() and mpd_response_finish(). * * @param connection the connection to MPD * @param channel the channel name * @return true on success * * @since libmpdclient 2.5 */ bool mpd_run_subscribe(struct mpd_connection *connection, const char *channel); /** * Sends the "unsubscribe" command: unsubscribe from a message * channel. * * @param connection the connection to MPD * @param channel the channel name * @return true on success * * @since libmpdclient 2.5 */ bool mpd_send_unsubscribe(struct mpd_connection *connection, const char *channel); /** * Shortcut for mpd_send_unsubscribe() and mpd_response_finish(). * * @param connection the connection to MPD * @param channel the channel name * @return true on success * * @since libmpdclient 2.5 */ bool mpd_run_unsubscribe(struct mpd_connection *connection, const char *channel); /** * Sends the "sendmessage" command: send a message to a channel. * * @param connection the connection to MPD * @param channel the channel name * @param text the message text * @return true on success * * @since libmpdclient 2.5 */ bool mpd_send_send_message(struct mpd_connection *connection, const char *channel, const char *text); /** * Shortcut for mpd_send_send_message() and mpd_response_finish(). * * @param connection the connection to MPD * @param channel the channel name * @param text the message text * @return true on success * * @since libmpdclient 2.5 */ bool mpd_run_send_message(struct mpd_connection *connection, const char *channel, const char *text); /** * Sends the "readmessages" command: send a message to a channel. * * @param connection the connection to MPD * @return true on success * * @since libmpdclient 2.5 */ bool mpd_send_read_messages(struct mpd_connection *connection); /** * Reads the next mpd_message from the MPD response. Free the return * value with mpd_message_free(). * * @return a mpd_message object on success, NULL on error or * end-of-response * * @since libmpdclient 2.5 */ mpd_malloc struct mpd_message * mpd_recv_message(struct mpd_connection *connection); /** * Sends the "channels" command: get a list of all channels. * * @param connection the connection to MPD * @return true on success * * @since libmpdclient 2.5 */ bool mpd_send_channels(struct mpd_connection *connection); /** * Receives the next channel name. Call this in a loop after * mpd_send_channels(). * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection * @returns a "channel" pair, or NULL on error or if the end of the * response is reached * * @since libmpdclient 2.5 */ mpd_malloc static inline struct mpd_pair * mpd_recv_channel_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "channel"); } #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/mixer.h000066400000000000000000000043551505242054600234470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Functions for manipulating MPD's mixer controls. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_MIXER_H #define MPD_MIXER_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sets the volume of all output devices. * * @param connection the connection to MPD * @param volume the volume, an integer between 0 and 100 * @return true on success, false on error */ bool mpd_send_set_volume(struct mpd_connection *connection, unsigned volume); /** * Shortcut for mpd_send_set_volume() and mpd_response_finish(). * * @param connection the connection to MPD * @param volume the volume, an integer between 0 and 100 * @return true on success, false on error */ bool mpd_run_set_volume(struct mpd_connection *connection, unsigned volume); /** * Changes the volume of all output devices. * * @param connection the connection to MPD * @param relative_volume the relative volume, an integer between -100 and 100 * @return true on success, false on error * * @since libmpdclient 2.9 */ bool mpd_send_change_volume(struct mpd_connection *connection, int relative_volume); /** * Shortcut for mpd_send_change_volume() and mpd_response_finish(). * * @param connection the connection to MPD * @param relative_volume the relative volume, an integer between -100 and 100 * @return true on success, false on error * * @since libmpdclient 2.9 */ bool mpd_run_change_volume(struct mpd_connection *connection, int relative_volume); /** * Sends the "getvol" command to MPD. Call mpd_recv_pair() to * read the response line. * * @param connection a valid and connected #mpd_connection * @return true on success * * @since libmpdclient 2.20, MPD 0.23 */ bool mpd_send_get_volume(struct mpd_connection *connection); /** * Shortcut for mpd_send_get_volume(), mpd_recv_pair_named() and * mpd_response_finish(). * * @param connection a valid and connected #mpd_connection * @return volume on success or -1 on error * * @since libmpdclient 2.20, MPD 0.23 */ int mpd_run_get_volume(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/mount.h000066400000000000000000000071341505242054600234630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_MOUNT_H #define MPD_MOUNT_H #include "compiler.h" #include struct mpd_connection; struct mpd_pair; /** * \struct mpd_mount * * This type represents a mount point on the MPD server. */ struct mpd_mount; #ifdef __cplusplus extern "C" { #endif /** * Begins parsing a new #mpd_mount. * * @param pair the first pair in this mount point * @return the new #mpd_mount object, or NULL on error (out of * memory, or wrong pair name) * * @since libmpdclient 2.16 */ mpd_malloc struct mpd_mount * mpd_mount_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_mount object. * * @return true if the pair was parsed and added to the mount (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next mount * * @since libmpdclient 2.16 */ bool mpd_mount_feed(struct mpd_mount *mnt, const struct mpd_pair *pair); /** * Frees a mpd_mount object returned from mpd_recv_mount() or mpd_mount_begin(). * * @since libmpdclient 2.16 */ void mpd_mount_free(struct mpd_mount *mount); /** * @return the mount point URI of the specified #mpd_mount object * * @since libmpdclient 2.16 */ mpd_pure const char * mpd_mount_get_uri(const struct mpd_mount *mnt); /** * @return the mounted storage URI of the specified #mpd_mount object; * may be NULL if MPD did not reveal it * * @since libmpdclient 2.16 */ mpd_pure const char * mpd_mount_get_storage(const struct mpd_mount *mnt); /** * Sends the "listmounts" command to MPD. Call mpd_recv_mount() to * read the response. * * @param connection a valid and connected mpd_connection. * @return true on success * * @since libmpdclient 2.16, MPD 0.19 */ bool mpd_send_list_mounts(struct mpd_connection *connection); /** * Reads the next mpd_mount from the MPD response. Free the return * value with mpd_mount_free(). * * @return a mpd_mount object on success, NULL on error or * end-of-response * * @since libmpdclient 2.16, MPD 0.19 */ mpd_malloc struct mpd_mount * mpd_recv_mount(struct mpd_connection *connection); /** * Sends the "mount" command to MPD. * * @param connection a valid and connected mpd_connection. * @param uri the mount point URI * @param storage the mounted storage URI * @return true on success * * @since libmpdclient 2.16, MPD 0.19 */ bool mpd_send_mount(struct mpd_connection *connection, const char *uri, const char *storage); /** * Shortcut for mpd_send_mount() and mpd_response_finish(). * * @param connection A valid and connected mpd_connection. * @param uri the mount point URI * @param storage the mounted storage URI * @return true on success * * @since libmpdclient 2.16, MPD 0.19 */ bool mpd_run_mount(struct mpd_connection *connection, const char *uri, const char *storage); /** * Sends the "unmount" command to MPD. * * @param connection a valid and connected mpd_connection. * @param uri the mount point URI * @return true on success * * @since libmpdclient 2.16, MPD 0.19 */ bool mpd_send_unmount(struct mpd_connection *connection, const char *uri); /** * Shortcut for mpd_send_unmount() and mpd_response_finish(). * * @param connection A valid and connected mpd_connection. * @param uri the mount point URI * @return true on success * * @since libmpdclient 2.16, MPD 0.19 */ bool mpd_run_unmount(struct mpd_connection *connection, const char *uri); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/neighbor.h000066400000000000000000000050051505242054600241110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_NEIGHBOR_H #define MPD_NEIGHBOR_H #include "compiler.h" #include struct mpd_connection; struct mpd_pair; /** * \struct mpd_neighbor * * This type represents a neighbor (accessible file servers on the local net) * on the MPD server. */ struct mpd_neighbor; #ifdef __cplusplus extern "C" { #endif /** * Begins parsing a new #mpd_neighbor. * * @param pair the first pair in this mount point * @return the new #mpd_neighbor object, or NULL on error (out of * memory, or wrong pair name) * * @since libmpdclient 2.17 */ mpd_malloc struct mpd_neighbor * mpd_neighbor_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_neighbor object. * * @return true if the pair was parsed and added to the mpd_neighbor (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next neighbor * * @since libmpdclient 2.17 */ bool mpd_neighbor_feed(struct mpd_neighbor *neighbor, const struct mpd_pair *pair); /** * Frees a #mpd_neighbor object returned from mpd_recv_neighbor() or * mpd_neighbor_begin(). * * @since libmpdclient 2.17 */ void mpd_neighbor_free(struct mpd_neighbor *neighbor); /** * @return the neighbor mount point URI of the specified #mpd_neighbor object * * @since libmpdclient 2.17 */ mpd_pure const char * mpd_neighbor_get_uri(const struct mpd_neighbor *neighbor); /** * @return the display name of the specified #mpd_neighbor object; * * @since libmpdclient 2.17 */ mpd_pure const char * mpd_neighbor_get_display_name(const struct mpd_neighbor *neighbor); /** * Sends the "listneighbors" command to MPD: queries a list of "neighbors" * (e.g. accessible file servers on the local net). Call mpd_recv_neighbor() to * read the response. * * @param connection a valid and connected mpd_connection. * @return true on success * * @since libmpdclient 2.17, MPD 0.19 */ bool mpd_send_list_neighbors(struct mpd_connection *connection); /** * Reads the next mpd_neighbor from the MPD response. Free the return * value with mpd_neighbor_free(). * * @return a mpd_neighbor object on success, NULL on error or * end-of-response * * @since libmpdclient 2.17, MPD 0.19 */ mpd_malloc struct mpd_neighbor * mpd_recv_neighbor(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/output.h000066400000000000000000000155051505242054600236620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_OUTPUT_H #define MPD_OUTPUT_H #include "compiler.h" #include struct mpd_connection; struct mpd_pair; /** * \struct mpd_output * * This type represents an audio output device on the MPD server. */ struct mpd_output; #ifdef __cplusplus extern "C" { #endif /** * Begins parsing a new #mpd_output. * * @param pair the first pair in this output (name is "outputid") * @return the new #mpd_output object, or NULL on error (out of * memory, or wrong pair name) */ mpd_malloc struct mpd_output * mpd_output_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_output object. * * @return true if the pair was parsed and added to the output (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next output */ bool mpd_output_feed(struct mpd_output *output, const struct mpd_pair *pair); /** * Frees a mpd_output object returned from mpd_recv_output() or * mpd_output_begin(). */ void mpd_output_free(struct mpd_output *output); /** * @return the id of the specified #mpd_output object */ mpd_pure unsigned mpd_output_get_id(const struct mpd_output *output); /** * @return the configured name of the specified #mpd_output object */ mpd_pure const char * mpd_output_get_name(const struct mpd_output *output); /** * @return the plugin of the specified #mpd_output object, or NULL if * none was specified by the server * * @since libmpdclient 2.14, MPD 0.21 */ mpd_pure const char * mpd_output_get_plugin(const struct mpd_output *output); /** * @return true if this output is enabled */ mpd_pure bool mpd_output_get_enabled(const struct mpd_output *output); /** * Find an attribute with the given name and return its value. * * @return the attribute value or NULL if there is no such attributes * * @since libmpdclient 2.16, MPD 0.21 */ mpd_pure const char * mpd_output_get_attribute(const struct mpd_output *output, const char *name); /** * Obtains the first attribute for this output. This rewinds the * current attribute pointer to the start. Call * mpd_output_next_attribute() to obtain more attributes. * * @return a pointer to the first attribute or NULL if there are no * attributes * * @since libmpdclient 2.14, MPD 0.21 */ const struct mpd_pair * mpd_output_first_attribute(struct mpd_output *output); /** * Obtains the next attribute for this output. Call this function * repeatedly until it returns NULL to get a full list of attributes. * * @return a pointer to the next attribute or NULL if there are no * more attributes * * @since libmpdclient 2.14, MPD 0.21 */ const struct mpd_pair * mpd_output_next_attribute(struct mpd_output *output); /** * Sends the "outputs" command to MPD: fetch information about all outputs. * Call mpd_recv_output() to read the response. * * @param connection A valid and connected mpd_connection. * @return true on success */ bool mpd_send_outputs(struct mpd_connection *connection); /** * Reads the next mpd_output from the MPD response. Free the return * value with mpd_output_free(). * * @return a mpd_output object on success, NULL on error or * end-of-response */ mpd_malloc struct mpd_output * mpd_recv_output(struct mpd_connection *connection); /** * Sends the "enableoutput" command to MPD. * * @param connection A valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success */ bool mpd_send_enable_output(struct mpd_connection *connection, unsigned output_id); /** * Shortcut for mpd_send_enable_output() and mpd_response_finish(). * * @param connection A valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success */ bool mpd_run_enable_output(struct mpd_connection *connection, unsigned output_id); /** * Sends the "disableoutput" command to MPD. * * @param connection A valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success */ bool mpd_send_disable_output(struct mpd_connection *connection, unsigned output_id); /** * Shortcut for mpd_send_disable_output() and mpd_response_finish(). * * @param connection A valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success */ bool mpd_run_disable_output(struct mpd_connection *connection, unsigned output_id); /** * Sends the "toggleoutput" command to MPD. * * @param connection a valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success * * @since libmpdclient 2.9 */ bool mpd_send_toggle_output(struct mpd_connection *connection, unsigned output_id); /** * Shortcut for mpd_send_toggle_output() and mpd_response_finish(). * * @param connection a valid and connected mpd_connection. * @param output_id an identifier for the output device (see * mpd_recv_output()) * @return true on success * * @since libmpdclient 2.9 */ bool mpd_run_toggle_output(struct mpd_connection *connection, unsigned output_id); /** * Sends the "outputset" command to MPD: set a runtime attribute for the * specified output_id. * * @param connection a valid and connected mpd_connection * @param output_id an identifier for the output device (see * mpd_recv_output()) * @param attribute_name the attribute name * @param attribute_value the attribute value * @return true on success * * @since libmpdclient 2.14, MPD 0.21 */ bool mpd_send_output_set(struct mpd_connection *connection, unsigned output_id, const char *attribute_name, const char *attribute_value); /** * Shortcut for mpd_send_output_set() and mpd_response_finish(). * * @since libmpdclient 2.14, MPD 0.21 */ bool mpd_run_output_set(struct mpd_connection *connection, unsigned output_id, const char *attribute_name, const char *attribute_value); /** * Move an output to the current partition. * * @param connection the connection to MPD * @param output_name the name of the output to be moved * @return true on success * * @since libmpdclient 2.18, MPD 0.22. */ bool mpd_send_move_output(struct mpd_connection *connection, const char *output_name); /** * Shortcut for mpd_send_move_output() and mpd_response_finish(). * * @param connection the connection to MPD * @param output_name the name of the output to be moved * @return true on success * * @since libmpdclient 2.18, MPD 0.22. */ bool mpd_run_move_output(struct mpd_connection *connection, const char *output_name); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/pair.h000066400000000000000000000007031505242054600232470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_PAIR_H #define LIBMPDCLIENT_PAIR_H /** * A name-value pair received from the MPD server. */ struct mpd_pair { /** the name of the element */ const char *name; /** the value of the element */ const char *value; }; #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/parser.h000066400000000000000000000071621505242054600236160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef LIBMPDCLIENT_PARSER_H #define LIBMPDCLIENT_PARSER_H #include "protocol.h" #include "compiler.h" #include enum mpd_parser_result { /** * Response line was not understood. */ MPD_PARSER_MALFORMED, /** * MPD has returned "OK" or "list_OK" (check with * mpd_parser_is_discrete()). */ MPD_PARSER_SUCCESS, /** * MPD has returned "ACK" with an error code. Call * mpd_parser_get_server_error() to get the error code. */ MPD_PARSER_ERROR, /** * MPD has returned a name-value pair. Call * mpd_parser_get_name() and mpd_parser_get_value(). */ MPD_PARSER_PAIR, }; /** * \struct mpd_parser * * This opaque object is a low-level parser for the MPD protocol. You * feed it with input lines, and it provides parsed representations. */ struct mpd_parser; #ifdef __cplusplus extern "C" { #endif /** * Allocates a new mpd_parser object. Returns NULL on error (out of * memory). */ mpd_malloc struct mpd_parser * mpd_parser_new(void); /** * Frees a mpd_parser object. */ void mpd_parser_free(struct mpd_parser *parser); /** * Feeds a line (without the trailing newline character) received from * MPD / mpd_async_recv_line() into the parser. * * Note that the line parameter is writable, because the parser will * modify it. The functions mpd_parser_get_name() and * mpd_parser_get_value() will return pointers inside this buffer. * This means that after passing the line to this function, you must * not modify or free it, until the name and value pointers are not * used anymore. * * @param parser the #mpd_parser object * @param line a line received from the MPD server * @return a result code indicating the type of line, or error */ enum mpd_parser_result mpd_parser_feed(struct mpd_parser *parser, char *line); /** * Call this when mpd_parser_feed() has returned #MPD_PARSER_SUCCESS * to find out whether this is an "OK" (false) or a "list_OK" (true) * response. * * @param parser the #mpd_parser object */ mpd_pure bool mpd_parser_is_discrete(const struct mpd_parser *parser); /** * Call this when mpd_parser_feed() has returned #MPD_PARSER_ERROR to * obtain the reason for the error. * * @param parser the #mpd_parser object */ mpd_pure enum mpd_server_error mpd_parser_get_server_error(const struct mpd_parser *parser); /** * On #MPD_PARSER_ERROR, this returns the number of the list command * which failed. Don't call this outside of a command list. * * @param parser the #mpd_parser object */ mpd_pure unsigned mpd_parser_get_at(const struct mpd_parser *parser); /** * On #MPD_PARSER_ERROR, this returns the human readable error message * returned by MPD (UTF-8). * * This returns a pointer into the line buffer passed to * mpd_parser_feed(). It is valid as long as the buffer is not * freed/modified. * * @param parser the #mpd_parser object */ mpd_pure const char * mpd_parser_get_message(const struct mpd_parser *parser); /** * On #MPD_PARSER_PAIR, this returns the name. * * This returns a pointer into the line buffer passed to * mpd_parser_feed(). It is valid as long as the buffer is not * freed/modified. * * @param parser the #mpd_parser object */ mpd_pure const char * mpd_parser_get_name(const struct mpd_parser *parser); /** * On #MPD_PARSER_PAIR, this returns the value. * * This returns a pointer into the line buffer passed to * mpd_parser_feed(). It is valid as long as the buffer is not * freed/modified. * * @param parser the #mpd_parser object */ mpd_pure const char * mpd_parser_get_value(const struct mpd_parser *parser); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/partition.h000066400000000000000000000101741505242054600243300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_PARTITION_H #define MPD_PARTITION_H #include "recv.h" #include "compiler.h" #include struct mpd_pair; /** * \struct mpd_partition */ struct mpd_partition; struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Creates a new partition object from the pair received from MPD server. * * @param pair a #mpd_pair received from MPD (name must be "partition") * @return the new #mpd_partition object, or NULL on error (out of * memory, or pair name is not "partition") * * @since libmpdclient 2.17 */ mpd_malloc struct mpd_partition * mpd_partition_new(const struct mpd_pair *pair); /** * Frees a #mpd_partition object. * * @since libmpdclient 2.17 */ void mpd_partition_free(struct mpd_partition *partition); /** * Returns the partition name. * * @since libmpdclient 2.17 */ mpd_pure const char * mpd_partition_get_name(const struct mpd_partition *partition); /** * Creates a new partition. * A partition is one frontend of a multi-player MPD process: it has separate * queue, player and outputs. A client is assigned to one partition at a time. * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.17 */ bool mpd_send_newpartition(struct mpd_connection *connection, const char *partition); /** * Shortcut for mpd_send_newpartition() and mpd_response_finish(). * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.17 */ bool mpd_run_newpartition(struct mpd_connection *connection, const char *partition); /** * Delete a partition. * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.18, MPD 0.22 */ bool mpd_send_delete_partition(struct mpd_connection *connection, const char *partition); /** * Shortcut for mpd_send_delete_partition() and mpd_response_finish(). * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.18, MPD 0.22 */ bool mpd_run_delete_partition(struct mpd_connection *connection, const char *partition); /** * Switch the client to a different partition. * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.17 */ bool mpd_send_switch_partition(struct mpd_connection *connection, const char *partition); /** * Shortcut for mpd_send_switch_partition() and mpd_response_finish(). * * @param connection the connection to MPD * @param partition the partition name * @return true on success * * @since libmpdclient 2.17 */ bool mpd_run_switch_partition(struct mpd_connection *connection, const char *partition); /** * Sends the "listpartitions" command: request the list of partitions. * Call mpd_recv_partition() repeatedly to read the response. * * @param connection the connection to MPD * @return true on success * * @since libmpdclient 2.17 */ bool mpd_send_listpartitions(struct mpd_connection *connection); /** * Receives the next partition name. Call this in a loop after * mpd_send_listpartitions(). * * Free the return value with mpd_return_pair(). * * @param connection a #mpd_connection object * @returns a "partition" pair, or NULL on error or if the end of the * response is reached * * @since libmpdclient 2.17 */ mpd_malloc static inline struct mpd_pair * mpd_recv_partition_pair(struct mpd_connection *connection) { return mpd_recv_pair_named(connection, "partition"); } /** * Reads the next #mpd_partition from the MPD response. Free the * return value with mpd_partition_free(). * * @return a mpd_partition object on success, NULL on error or * end-of-response * * @since libmpdclient 2.18 */ mpd_malloc struct mpd_partition * mpd_recv_partition(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/password.h000066400000000000000000000013431505242054600241570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Password authentication. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_PASSWORD_H #define MPD_PASSWORD_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sends the password to MPD, to gain more privileges. */ bool mpd_send_password(struct mpd_connection *connection, const char *password); /** * Sends the password to MPD and receives its response. * * @return true on success, false on failure */ bool mpd_run_password(struct mpd_connection *connection, const char *password); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/player.h000066400000000000000000000415451505242054600236210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Controlling playback. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_PLAYER_H #define MPD_PLAYER_H #include "compiler.h" #include "status.h" #include struct mpd_connection; struct mpd_song; #ifdef __cplusplus extern "C" { #endif /** * There are two ways to address songs within the queue: by their position and * by their id. * The position is a 0-based index. It is unstable by design: if you move, * delete or insert songs, all following indices will change, and a client can * never be sure what song is behind a given index/position. * * Song ids on the other hand are stable: an id is assigned to a song when it * is added, and will stay the same, no matter how much it is moved around. * Adding the same song twice will assign different ids to them, and a * deleted-and-readded song will have a new id. This way, a client can always * be sure the correct song is being used. * * Many commands come in two flavors, one for each address type. Whenever * possible, ids should be used. */ /** * Fetches the currently selected song (the song referenced by * mpd_status_get_song_id()). * Call mpd_recv_song() to receive the response. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_current_song(struct mpd_connection *connection); /** * Shortcut for mpd_send_current_song() and mpd_recv_song(). * * @param connection the connection to MPD * @return the current song, or NULL on error or if there is no * current song */ mpd_malloc struct mpd_song * mpd_run_current_song(struct mpd_connection *connection); /** * Starts playing the current song from the beginning. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_play(struct mpd_connection *connection); /** * Shortcut for mpd_send_play() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_play(struct mpd_connection *connection); /** * Starts playing the specified song from the beginning. * * @param connection the connection to MPD * @param song_pos the position of the song in the queue * @return true on success, false on error */ bool mpd_send_play_pos(struct mpd_connection *connection, unsigned song_pos); /** * Shortcut for mpd_send_play() and mpd_response_finish(). * * @param connection the connection to MPD * @param song_pos the position of the song in the queue * @return true on success, false on error */ bool mpd_run_play_pos(struct mpd_connection *connection, unsigned song_pos); /** * Starts playing the specified song from the beginning. * * @param connection the connection to MPD * @param song_id the id of the song * @return true on success, false on error */ bool mpd_send_play_id(struct mpd_connection *connection, unsigned song_id); /** * Shortcut for mpd_send_play_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param song_id the id of the song * @return true on success, false on error */ bool mpd_run_play_id(struct mpd_connection *connection, unsigned song_id); /** * Stops playing the current song. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_stop(struct mpd_connection *connection); /** * Shortcut for mpd_send_stop() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_stop(struct mpd_connection *connection); /** * This function uses a deprecated feature of MPD, you should avoid it. * * Toggles the pause mode by sending "pause" without arguments. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_toggle_pause(struct mpd_connection *connection); /** * This function uses a deprecated feature of MPD, you should avoid it. * Shortcut for mpd_send_toggle_pause() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_toggle_pause(struct mpd_connection *connection); /** * Pauses/Resumes playing the current song. * If mode is true, MPD pauses the song; otherwise, MPD resumes the song. * * @param connection the connection to MPD * @param mode if true: pause, if false: resume * @return true on success, false on error */ bool mpd_send_pause(struct mpd_connection *connection, bool mode); /** * Shortcut for mpd_send_pause() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode if true: pause, if false: resume * @return true on success, false on error */ bool mpd_run_pause(struct mpd_connection *connection, bool mode); /** * Play the next song in the playlist. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_next(struct mpd_connection *connection); /** * Shortcut for mpd_send_next() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_next(struct mpd_connection *connection); /** * Play the previous song in the playlist. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_previous(struct mpd_connection *connection); /** * Shortcut for mpd_send_previous() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_previous(struct mpd_connection *connection); /** * Seeks to the position t (in seconds) of position song_pos in the playlist. * * @param connection the connection to MPD * @param song_pos the position of the song in the queue * @param t the position within the song, in seconds * @return true on success, false on error */ bool mpd_send_seek_pos(struct mpd_connection *connection, unsigned song_pos, unsigned t); /** * Shortcut for mpd_send_seek_pos() and mpd_response_finish(). * * @param connection the connection to MPD * @param song_pos the position of the song in the queue * @param t the position within the song, in seconds * @return true on success, false on error */ bool mpd_run_seek_pos(struct mpd_connection *connection, unsigned song_pos, unsigned t); /** * Seeks to the position t (in seconds) of song id song_id. * * @param connection the connection to MPD * @param song_id the id of the song * @param t the position within the song, in seconds * @return true on success, false on error */ bool mpd_send_seek_id(struct mpd_connection *connection, unsigned song_id, unsigned t); /** * Shortcut for mpd_send_seek_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param song_id the id of the song * @param t the position within the song, in seconds * @return true on success, false on error */ bool mpd_run_seek_id(struct mpd_connection *connection, unsigned song_id, unsigned t); /** * Seeks to the position t (in seconds; fractions allowed) of song id song_id. * * @param connection the connection to MPD * @param song_id the id of the song * @param t the position within the song, in seconds (fractions allowed) * @return true on success, false on error */ bool mpd_send_seek_id_float(struct mpd_connection *connection, unsigned song_id, float t); /** * Shortcut for mpd_send_seek_id_float() and mpd_response_finish(). * * @param connection the connection to MPD * @param song_id the id of the song * @param t the position within the song, in seconds (fractions allowed) * @return true on success, false on error */ bool mpd_run_seek_id_float(struct mpd_connection *connection, unsigned song_id, float t); /** * Seeks the current song. * * @param connection the connection to MPD * @param t the position within the song, in seconds * @param relative true makes #t a relative to the current position * @return true on success, false on error * * @since MPD 0.17, libmpdclient 2.15 */ bool mpd_send_seek_current(struct mpd_connection *connection, float t, bool relative); /** * Shortcut for mpd_send_seek_current() and mpd_response_finish(). * * @param connection the connection to MPD * @param t the new position (in seconds) * @param relative true to seek relative to the current position and * false to seek to an absolute time stamp within the song * @return true on success, false on error * * @since MPD 0.17, libmpdclient 2.15 */ bool mpd_run_seek_current(struct mpd_connection *connection, float t, bool relative); /** * Sets repeat on/off for the current song. * If mode is true, MPD repeats the song; otherwise, MPD does not repeat the * song. * * @param connection the connection to MPD * @param mode if true: repeat, if false: do not repeat * @return true on success, false on error */ bool mpd_send_repeat(struct mpd_connection *connection, bool mode); /** * Shortcut for mpd_send_repeat() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode if true: pause, if false: resume * @return true on success, false on error */ bool mpd_run_repeat(struct mpd_connection *connection, bool mode); /** * Sets random mode on/off for the queue. * If mode is true, MPD enables random mode; otherwise, MPD disables random * mode. * * @param connection the connection to MPD * @param mode if true: enable random mode, if false: disable random mode * @return true on success, false on error */ bool mpd_send_random(struct mpd_connection *connection, bool mode); /** * Shortcut for mpd_send_random() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode if true: enable random mode, if false: disable random mode * @return true on success, false on error */ bool mpd_run_random(struct mpd_connection *connection, bool mode); /** * Sets single state for the playlist. * If state is #MPD_SINGLE_ON, MPD enables single mode: playback is stopped * after current song, or song is repeated if the repeat mode is enabled. * * If state is #MPD_SINGLE_OFF, MPD disables single mode: if random mode is * enabled, the playlist order is shuffled after it is played completely. * * If state is #MPD_SINGLE_ONESHOT, MPD enables single mode temporarily: single * mode is disabled (#MPD_SINGLE_OFF) after a song has been played and there is * another song in the current playlist. * * @param connection the connection to MPD * @param state the desired single mode state * @return true on success, false on error or state is #MPD_SINGLE_UNKNOWN * * @since MPD 0.21, libmpdclient 2.18. */ bool mpd_send_single_state(struct mpd_connection *connection, enum mpd_single_state state); /** * Shortcut for mpd_send_single_state() and mpd_response_finish(). * * @param connection the connection to MPD * @param state the desired single mode state * @return true on success, false on error or state is #MPD_SINGLE_UNKNOWN * * @since MPD 0.21, libmpdclient 2.18. */ bool mpd_run_single_state(struct mpd_connection *connection, enum mpd_single_state state); /** * Sets single mode on/off for the playlist. * This function does not support the 'oneshot' state for single mode: use * mpd_send_single_state() instead. * * If mode is true, MPD enables single mode: playback is stopped after current * song, or song is repeated if the repeat mode is enabled. * * If mode is false, MPD disables single mode: if random mode is enabled, the * playlist order is shuffled after it is played completely. * * @param connection the connection to MPD * @param mode if true: enable single mode, if false: disable single mode * @return true on success, false on error * * @since MPD 0.15 */ bool mpd_send_single(struct mpd_connection *connection, bool mode); /** * Shortcut for mpd_send_single() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode if true: enable single mode, if false: disable single mode * @return true on success, false on error * * @since MPD 0.15 */ bool mpd_run_single(struct mpd_connection *connection, bool mode); /** * Sets consume mode on/off for the playlist. * If mode is true, MPD enables consume mode: each song played is removed from * the playlist. * * This function does not support the 'oneshot' state for consume mode: use * mpd_send_consume_state() instead. * * If mode is false, MPD disables consume mode. * * @param connection the connection to MPD * @param mode if true: enable consume mode, if false: disable consume mode * @return true on success, false on error * * @since MPD 0.15 */ bool mpd_send_consume(struct mpd_connection *connection, bool mode); /** * Shortcut for mpd_send_consume() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode if true: enable consume mode, if false: disable consume mode * @return true on success, false on error * * @since MPD 0.15 */ bool mpd_run_consume(struct mpd_connection *connection, bool mode); /** * Sets consume state for the playlist. * If state is #MPD_CONSUME_ON, MPD enables consume mode: each song played is removed from * the playlist. * * If state is #MPD_CONSUME_OFF, MPD disables consume mode. * * If state is #MPD_CONSUME_ONESHOT, MPD enables consume mode temporarily: consume * mode is disabled (#MPD_CONSUME_OFF) after a song has been played. * * @param connection the connection to MPD * @param state the desired single mode state * @return true on success, false on error or state is #MPD_SINGLE_UNKNOWN * * @since MPD 0.24, libmpdclient 2.21. */ bool mpd_send_consume_state(struct mpd_connection *connection, enum mpd_consume_state state); /** * Shortcut for mpd_send_consume_state() and mpd_response_finish(). * * @param connection the connection to MPD * @param state the desired single mode state * @return true on success, false on error or state is #MPD_SINGLE_UNKNOWN * * @since MPD 0.24, libmpdclient 2.21. */ bool mpd_run_consume_state(struct mpd_connection *connection, enum mpd_consume_state state); /** * Sets crossfading of seconds between songs on for the playlist. * Crossfading only happens when the songs audio format are the same. * * @param connection the connection to MPD * @param seconds seconds of crossfading between songs * @return true on success, false on error */ bool mpd_send_crossfade(struct mpd_connection *connection, unsigned seconds); /** * Shortcut for mpd_send_crossfade() and mpd_response_finish(). * * @param connection the connection to MPD * @param seconds seconds of crossfading between songs * @return true on success, false on error */ bool mpd_run_crossfade(struct mpd_connection *connection, unsigned seconds); /** * Sets the threshold at which songs will be overlapped. Like crossfading but * doesn't fade the track volume, just overlaps. * * The songs need to have MixRamp tags added by an external tool. 0dB is the * normalized maximum volume; so use negative values (I prefer -17dB). In the * absence of MixRamp tags, crossfading will be used. * * @param connection the connection to MPD * @param db decibels of volume for overlapping songs * @return true on success, false on error * * @since libmpdclient 2.2 */ bool mpd_send_mixrampdb(struct mpd_connection *connection, float db); /** * Shortcut for mpd_send_mixrampdb() and mpd_response_finish(). * * @param connection the connection to MPD * @param db decibels of volume for overlapping songs * @return true on success, false on error * * @since libmpdclient 2.2 */ bool mpd_run_mixrampdb(struct mpd_connection *connection, float db); /** * Sets additional time subtracted from the overlap calculated by mixrampdb. * A value of NaN disables MixRamp overlapping and falls back to crossfading. * * @param connection the connection to MPD * @param seconds seconds subtracted from the overlap calculated by mixrampdb * @return true on success, false on error * * @since libmpdclient 2.2 */ bool mpd_send_mixrampdelay(struct mpd_connection *connection, float seconds); /** * Shortcut for mpd_send_mixrampdelay() and mpd_response_finish(). * * @param connection the connection to MPD * @param seconds seconds subtracted from the overlap calculated by mixrampdb * @return true on success, false on error * * @since libmpdclient 2.2 */ bool mpd_run_mixrampdelay(struct mpd_connection *connection, float seconds); /** * Clears the current error message in MPD's status (this is also accomplished * by any command that starts playback). * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.4 */ bool mpd_send_clearerror(struct mpd_connection *connection); /** * Shortcut for mpd_send_clearerror() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.4 */ bool mpd_run_clearerror(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/playlist.h000066400000000000000000000450711505242054600241640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Manipulate stored playlists. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_PLAYLIST_H #define LIBMPDCLIENT_PLAYLIST_H #include "compiler.h" #include "position.h" #include #include struct mpd_pair; struct mpd_connection; /** * \struct mpd_playlist * * An opaque representation for a playlist stored in MPD's * playlist directory. Use the functions provided by this header to * access the object's attributes. */ struct mpd_playlist; /** * MPDs queue save modes. * * @since libmpdclient 2.21, MPD 0.24. */ enum mpd_queue_save_mode { /** Create new playlist */ MPD_QUEUE_SAVE_MODE_CREATE = 0, /** Replace existing playlist */ MPD_QUEUE_SAVE_MODE_REPLACE, /** Append to existing playlist */ MPD_QUEUE_SAVE_MODE_APPEND, /** Unknown queue save mode */ MPD_QUEUE_SAVE_MODE_UNKNOWN }; #ifdef __cplusplus extern "C" { #endif /** * Free memory allocated by the #mpd_playlist object. */ void mpd_playlist_free(struct mpd_playlist *playlist); /** * Duplicates a #mpd_playlist object. * * @return the new object, or NULL on out of memory */ mpd_malloc struct mpd_playlist * mpd_playlist_dup(const struct mpd_playlist *playlist); /** * Returns the path name of this playlist file. It does not begin * with a slash. */ mpd_pure const char * mpd_playlist_get_path(const struct mpd_playlist *playlist); /** * @return the POSIX UTC time stamp of the last modification, or 0 if * that is unknown */ mpd_pure time_t mpd_playlist_get_last_modified(const struct mpd_playlist *playlist); /** * Begins parsing a new playlist. * * @param pair the first pair in this playlist (name must be * "playlist") * @return the new #mpd_playlist object, or NULL on error (out of * memory, or pair name is not "playlist") */ mpd_malloc struct mpd_playlist * mpd_playlist_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_playlist object. * * @return true if the pair was parsed and added to the playlist (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next playlist */ bool mpd_playlist_feed(struct mpd_playlist *playlist, const struct mpd_pair *pair); /** * Obtain a list of stored playlists. * Use mpd_recv_playlist() to read the playlists. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.5 */ bool mpd_send_list_playlists(struct mpd_connection *connection); /** * Receives the next playlist from the MPD server. * * @return a #mpd_playlist object, or NULL on error or if the playlist list is * finished */ mpd_malloc struct mpd_playlist * mpd_recv_playlist(struct mpd_connection *connection); /** * List the content of the stored playlist identified by name. * Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @param name the name of the playlist * @return true on success, false on error */ bool mpd_send_list_playlist(struct mpd_connection *connection, const char *name); /** * Like mpd_send_list_playlist(), but specifies a (position) range. * Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_list_playlist_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * List the content, with full metadata, of the stored playlist identified by * name. Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @param name the name of the playlist * @return true on success, false on error */ bool mpd_send_list_playlist_meta(struct mpd_connection *connection, const char *name); /** * Like mpd_send_list_playlist_meta(), but specifies a (position) range. * Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_list_playlist_range_meta(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * Clear the playlist name (i.e. truncate name.m3u) * * @param connection the connection to MPD * @param name the name of the playlist * @return true on success, false on error */ bool mpd_send_playlist_clear(struct mpd_connection *connection, const char *name); /** * Shortcut for mpd_send_playlist_clear() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @return true on success, false on error */ bool mpd_run_playlist_clear(struct mpd_connection *connection, const char *name); /** * Add a path to a playlist. The playlist will be created if it does not * exist. * * @param connection the connection to MPD * @param name the name of the playlist * @param path URI to be added * @return true on success, false on error */ bool mpd_send_playlist_add(struct mpd_connection *connection, const char *name, const char *path); /** * Shortcut for mpd_send_playlist_add() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param path URI to be added * @return true on success, false on error */ bool mpd_run_playlist_add(struct mpd_connection *connection, const char *name, const char *path); /** * Inserts a uri to a playlist for a given position. The playlist * will be created if it does not exist. * * @param connection the connection to MPD * @param name the name of the playlist * @param uri URI to be added * @param to the desired position * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_send_playlist_add_to(struct mpd_connection *connection, const char *name, const char *uri, unsigned to); /** * Shortcut for mpd_send_playlist_add_to() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param uri URI to be added * @param to the desired position * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_run_playlist_add_to(struct mpd_connection *connection, const char *name, const char *uri, unsigned to); /** * Move a song from one position to another in the same playlist. * * @param connection the connection to MPD * @param name the name of the playlist * @param from previous song place in the playlist * @param to next song position in the playlist * @return true on success, false on error */ bool mpd_send_playlist_move(struct mpd_connection *connection, const char *name, unsigned from, unsigned to); /** * Shortcut for mpd_send_playlist_move() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param from previous song place in the playlist * @param to next song position in the playlist * @return true on success, false on error * * @since libmpdclient 2.19 */ bool mpd_run_playlist_move(struct mpd_connection *connection, const char *name, unsigned from, unsigned to); /** * Moves a range of songs within the same playlist. * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.24 */ bool mpd_send_playlist_move_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to); /** * Shortcut for mpd_send_playlist_move_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.24 */ bool mpd_run_playlist_move_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to); /** * Delete a position from a playlist. * * @param connection the connection to MPD * @param name the name of the playlist * @param pos song position in the playlist * @return true on success, false on error */ bool mpd_send_playlist_delete(struct mpd_connection *connection, const char *name, unsigned pos); /** * Shortcut for mpd_send_playlist_delete() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param pos song position in the playlist * @return true on success, false on error */ bool mpd_run_playlist_delete(struct mpd_connection *connection, const char *name, unsigned pos); /** * Delete a range from a playlist. * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding) * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_send_playlist_delete_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * Shortcut for mpd_send_playlist_delete_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist * @param start the start position of the range (including) * @param end the end position of the range (excluding) * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_run_playlist_delete_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * Saves the current queue as a m3u file in the playlist directory * (i.e. name.m3u). * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error */ bool mpd_send_save(struct mpd_connection *connection, const char *name); /** * Shortcut for mpd_send_save() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error */ bool mpd_run_save(struct mpd_connection *connection, const char *name); /** * Saves the current queue as a m3u file in the playlist directory * (i.e. name.m3u). * This function supports the mode argument that can be * MPD_QUEUE_SAVE_MODE_CREATE: creates a new playlist, same as mpd_send_save * MPD_QUEUE_SAVE_MODE_REPLACE: replaces an existing playlist * MPD_QUEUE_SAVE_MODE_APPEND: appends to an existing playlist * * @since libmpdclient 2.21, MPD 0.24. * * @param connection the connection to MPD * @param name the name of the playlist file * @param mode the desired save mode * @return true on success, false on error */ bool mpd_send_save_queue(struct mpd_connection *connection, const char *name, enum mpd_queue_save_mode mode); /** * Shortcut for mpd_send_save_queue() and mpd_response_finish(). * * @since libmpdclient 2.21, MPD 0.24. * * @param connection the connection to MPD * @param name the name of the playlist file * @param mode the desired save mode * @return true on success, false on error */ bool mpd_run_save_queue(struct mpd_connection *connection, const char *name, enum mpd_queue_save_mode mode); /** * Looks up the name of the specified queue save mode. * * @return the name, or NULL if the queue save mode is not valid * * @since libmpdclient 2.21. */ const char * mpd_lookup_queue_save_mode(enum mpd_queue_save_mode mode); /** * Parse the string to check which queue save mode it contains. * * @return the queue save mode enum * * @since libmpdclient 2.21. */ enum mpd_queue_save_mode mpd_parse_queue_save_mode(const char *mode); /** * Load a stored playlist into the queue. * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error * * @since libmpdclient 2.0 */ bool mpd_send_load(struct mpd_connection *connection, const char *name); /** * Shortcut for mpd_send_load() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error * * @since libmpdclient 2.0 */ bool mpd_run_load(struct mpd_connection *connection, const char *name); /** * Like mpd_send_load(), but load only a portion of the playlist. * * @param connection the connection to MPD * @param name the name of the playlist file * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.16 */ bool mpd_send_load_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * Shortcut for mpd_send_load_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist file * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.16 */ bool mpd_run_load_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end); /** * Like mpd_send_load() or mpd_send_load_range(), but with range * and to parameters. * * @param connection the connection to MPD * @param name the name of the playlist file * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the desired position of the song * @param whence how to interpret the position parameter * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_send_load_range_to(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence); /** * Shortcut for mpd_send_load_range_to() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist file * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the desired position of the song * @param whence how to interpret the position parameter * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_run_load_range_to(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence); /** * Rename a playlist in the playlist directory. * * @param connection the connection to MPD * @param from the previous name of the playlist file * @param to the next name of the playlist file * @return true on success, false on error */ bool mpd_send_rename(struct mpd_connection *connection, const char *from, const char *to); /** * Shortcut for mpd_send_rename() and mpd_response_finish(). * * @param connection the connection to MPD * @param from the previous name of the playlist file * @param to the next name of the playlist file * @return true on success, false on error */ bool mpd_run_rename(struct mpd_connection *connection, const char *from, const char *to); /** * Remove a playlist from the playlist directory. * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error */ bool mpd_send_rm(struct mpd_connection *connection, const char *name); /** * Shortcut for mpd_send_rm() and mpd_response_finish(). * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error */ bool mpd_run_rm(struct mpd_connection *connection, const char *name); /** * Count the number of songs and their total playtime (seconds) in the * playlist. * * @param connection the connection to MPD * @param name the name of the playlist file * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_playlistlength(struct mpd_connection *connection, const char *name); /** * Search for songs in the stored playlist. * A window may be specified with mpd_playlist_search_add_window(). * Send the search command with mpd_playlist_search_commit(), and read the * response items with mpd_recv_song(). * * @param connection the connection to MPD * @param name the name of the stored playlist * @param expression the expression string; must be enclosed in * parentheses * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_playlist_search_begin(struct mpd_connection *connection, const char *name, const char *expression); /** * Request only a portion of the result set. * * @param connection a #mpd_connection * @param start the start offset (including) * @param end the end offset (not including) * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_playlist_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end); /** * Starts the real search. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_playlist_search_commit(struct mpd_connection *connection); /** * Cancels the search request before you have called * mpd_playlist_search_commit(). Call this to clear the current search * request. * * @param connection the connection to MPD * * @since libmpdclient 2.23, MPD 0.24 */ void mpd_playlist_search_cancel(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/position.h000066400000000000000000000016311505242054600241610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_POSITION_H #define LIBMPDCLIENT_POSITION_H enum mpd_position_whence { /** * The given number is an absolute position. 0 is the first * song. */ MPD_POSITION_ABSOLUTE, /** * The given number is a position after the current song. 0 * means right after the current song. */ MPD_POSITION_AFTER_CURRENT, /** * The given number is a position before the current song. 0 * means right before the current song. */ MPD_POSITION_BEFORE_CURRENT, }; /** * Looks up the character of the specified whence position. * * @return the charater, or "" if the whence position is absolute or not valid. */ const char * mpd_position_whence_char(enum mpd_position_whence whence); #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/protocol.h000066400000000000000000000013401505242054600241530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h or * mpd/parser.h instead. */ #ifndef MPD_PROTOCOL_H #define MPD_PROTOCOL_H enum mpd_server_error { MPD_SERVER_ERROR_UNK = -1, MPD_SERVER_ERROR_NOT_LIST = 1, MPD_SERVER_ERROR_ARG = 2, MPD_SERVER_ERROR_PASSWORD = 3, MPD_SERVER_ERROR_PERMISSION = 4, MPD_SERVER_ERROR_UNKNOWN_CMD = 5, MPD_SERVER_ERROR_NO_EXIST = 50, MPD_SERVER_ERROR_PLAYLIST_MAX = 51, MPD_SERVER_ERROR_SYSTEM = 52, MPD_SERVER_ERROR_PLAYLIST_LOAD = 53, MPD_SERVER_ERROR_UPDATE_ALREADY = 54, MPD_SERVER_ERROR_PLAYER_SYNC = 55, MPD_SERVER_ERROR_EXIST = 56, }; #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/queue.h000066400000000000000000000643031505242054600234460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Manipulate the queue (current playlist). * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_QUEUE_H #define MPD_QUEUE_H #include "compiler.h" #include "position.h" #include "tag.h" #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Consult mpd/playlist.h for the rationale on the preference of manipulating * song ids over positions in the queue. */ /** * Sends the "playlistinfo" command: list all songs in the queue * including meta information. * Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_list_queue_meta(struct mpd_connection *connection); /** * Like mpd_send_list_queue_meta(), but specifies a (position) range. * Use mpd_recv_entity() to receive the songs (#MPD_ENTITY_TYPE_SONG). * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_send_list_queue_range_meta(struct mpd_connection *connection, unsigned start, unsigned end); /** * Requests information (including tags) about one song in the * playlist (command "playlistid"). * Use mpd_recv_song() to obtain the song information. * * @param connection the connection to MPD * @param pos the position of the requested song */ bool mpd_send_get_queue_song_pos(struct mpd_connection *connection, unsigned pos); /** * Shortcut for mpd_send_get_queue_song_pos() and mpd_recv_song(). * * @param connection the connection to MPD * @param pos the position of the requested song * @return the song at the specified position, or NULL on error */ mpd_malloc struct mpd_song * mpd_run_get_queue_song_pos(struct mpd_connection *connection, unsigned pos); /** * Requests information (including tags) about one song in the * playlist (command "playlistid"). * Use mpd_recv_song() to obtain the song information. * * @param connection the connection to MPD * @param id the id of the requested song */ bool mpd_send_get_queue_song_id(struct mpd_connection *connection, unsigned id); /** * Shortcut for mpd_send_get_queue_song_id() and mpd_recv_song(). * * @param connection the connection to MPD * @param id the id of the requested song * @return the song at the specified id, or NULL on error */ mpd_malloc struct mpd_song * mpd_run_get_queue_song_id(struct mpd_connection *connection, unsigned id); /** * Request the queue changes from MPD since the specified version, * including tags. The MPD command is called "plchanges". * * The current version can be fetched with mpd_status_get_queue_version(). * Use mpd_recv_song() to receive the songs of the new version. * * @param connection the connection to MPD * @param version The playlist version you want the diff with. * @return true on success, false on error */ bool mpd_send_queue_changes_meta(struct mpd_connection *connection, unsigned version); /** * Same as mpd_send_queue_changes_meta(), but limit the result to a * range. * * The current version can be fetched with mpd_status_get_queue_version(). * Use mpd_recv_song() to receive the songs of the new queue. * * @param connection the connection to MPD * @param version The playlist version you want the diff with. * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.12 */ bool mpd_send_queue_changes_meta_range(struct mpd_connection *connection, unsigned version, unsigned start, unsigned end); /** * A more bandwidth efficient version of the * mpd_send_queue_changes_meta(). It only returns the position and id * of changed songs. The MPD command is called "plchangesposid". * * Use mpd_recv_queue_change_brief() for the response. * * @param connection A valid and connected mpd_connection. * @param version The playlist version you want the diff with. * @return true on success, false on error */ bool mpd_send_queue_changes_brief(struct mpd_connection *connection, unsigned version); /** * Same as mpd_send_queue_changes_brief(), but limit the result to a * range. * * Use mpd_recv_queue_change_brief() for the response. * * @param connection the connection to MPD * @param version The playlist version you want the diff with. * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.12 */ bool mpd_send_queue_changes_brief_range(struct mpd_connection *connection, unsigned version, unsigned start, unsigned end); /** * Receives a response element of mpd_send_queue_changes_brief() or * mpd_send_queue_changes_brief_range(). * * @param connection A valid and connected mpd_connection. * @param position_r reference to the position of the changed song * @param id_r reference to the id of the changed song * @return true on success, false on error or if there are no more * changes in this response */ bool mpd_recv_queue_change_brief(struct mpd_connection *connection, unsigned *position_r, unsigned *id_r); /** * Appends a song to the playlist: either a single file or a directory. * * @param connection A valid and connected mpd_connection. * @param uri URI of a song or directory (added recursively) * @return true on success, false on error */ bool mpd_send_add(struct mpd_connection *connection, const char *uri); /** * Shortcut for mpd_send_add() and mpd_response_finish(). * * @param connection the connection to MPD * @param uri URI of a song or directory (added recursively) * @return true on success, false on error */ bool mpd_run_add(struct mpd_connection *connection, const char *uri); /** * Inserts a song into the playlist for a given position: either a single file or a directory. * * @param connection A valid and connected mpd_connection. * @param uri URI of a song or directory (added recursively) * @param to the desired position of the song * @param whence how to interpret the position parameter * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_send_add_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence); /** * Shortcut for mpd_send_add_whence() and mpd_response_finish(). * * @param connection the connection to MPD * @param uri URI of a song or directory (added recursively) * @param to the desired position of the song * @param whence how to interpret the position parameter * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_run_add_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence); /** * Appends a song to the playlist. Call mpd_recv_song_id() for its id. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri URI of the song to be added * @return true on success, false on error */ bool mpd_send_add_id(struct mpd_connection *connection, const char *uri); /** * Inserts a song into the playlist for a given position, and returns its id. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri the URI of the song to be added * @param to the desired position of the song * @return true on success, false on error */ bool mpd_send_add_id_to(struct mpd_connection *connection, const char *uri, unsigned to); /** * Inserts a song into the playlist for a given position, and returns its id. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri the URI of the song to be added * @param to the desired position of the song * @param whence how to interpret the position parameter * @return true on success, false on error * * @since libmpdclient 2.20 */ bool mpd_send_add_id_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence); /** * Returns the id of the new song in the playlist. To be called after * mpd_send_add_id() or mpd_send_add_id_to(). * * @param connection the connection to MPD * @return the new song id, -1 on error or if MPD did not send an id */ int mpd_recv_song_id(struct mpd_connection *connection); /** * Executes the "addid" command and reads the response. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri URI of a song to be added * @return the new song id, -1 on error or if MPD did not send an id */ int mpd_run_add_id(struct mpd_connection *connection, const char *uri); /** * Executes the "addid" command and reads the response. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri the URI of the song to be added * @param to the desired position of the song * @return the new song id, -1 on error or if MPD did not send an id */ int mpd_run_add_id_to(struct mpd_connection *connection, const char *uri, unsigned to); /** * Executes the "addid" command and reads the response. * file is always a single file or URL. * * @param connection the connection to MPD * @param uri the URI of the song to be added * @param to the desired position of the song * @param whence how to interpret the position parameter * @return the new song id, -1 on error or if MPD did not send an id * * @since libmpdclient 2.20 */ int mpd_run_add_id_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence); /** * Deletes a song from the queue. * * @param connection the connection to MPD * @param pos the position of the song to be deleted * @return true on success, false on error */ bool mpd_send_delete(struct mpd_connection *connection, unsigned pos); /** * Shortcut for mpd_send_delete() and mpd_response_finish(). * * @param connection the connection to MPD * @param pos the position of the song to be deleted * @return true on success, false on error */ bool mpd_run_delete(struct mpd_connection *connection, unsigned pos); /** * Deletes songs from the queue. * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_send_delete_range(struct mpd_connection *connection, unsigned start, unsigned end); /** * Shortcut for mpd_send_delete_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_run_delete_range(struct mpd_connection *connection, unsigned start, unsigned end); /** * Deletes a song from the queue. * * @param connection the connection to MPD * @param id the id of the song to be deleted * @return true on success, false on error */ bool mpd_send_delete_id(struct mpd_connection *connection, unsigned id); /** * Shortcut for mpd_send_delete_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id the id of the song to be deleted * @return true on success, false on error */ bool mpd_run_delete_id(struct mpd_connection *connection, unsigned id); /** * Shuffles the queue. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_shuffle(struct mpd_connection *connection); /** * Shortcut for mpd_send_shuffle() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_shuffle(struct mpd_connection *connection); /** * Shuffles a range within the queue. * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_send_shuffle_range(struct mpd_connection *connection, unsigned start, unsigned end); /** * Shortcut for mpd_send_shuffle_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_run_shuffle_range(struct mpd_connection *connection, unsigned start, unsigned end); /** * Clear the queue. * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_send_clear(struct mpd_connection *connection); /** * Shortcut for mpd_send_clear() and mpd_response_finish(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_run_clear(struct mpd_connection *connection); /** * Moves a song within the queue. * * @param connection the connection to MPD * @param from the source song position * @param to the new position of the song * @return true on success, false on error */ bool mpd_send_move(struct mpd_connection *connection, unsigned from, unsigned to); /** * Shortcut for mpd_send_move() and mpd_response_finish(). * * @param connection the connection to MPD * @param from the source song position * @param to the new position of the song * @return true on success, false on error */ bool mpd_run_move(struct mpd_connection *connection, unsigned from, unsigned to); /** * Moves a song within the queue. * * @param connection the connection to MPD * @param from the source song position * @param to the new position of the song * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_send_move_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence); /** * Shortcut for mpd_send_move_whence() and mpd_response_finish(). * * @param connection the connection to MPD * @param from the source song position * @param to the new position of the song * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_run_move_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence); /** * Moves a song within the queue. * * @param connection the connection to MPD * @param from the source song id * @param to the new position of the song (not an id!) * @return true on success, false on error */ bool mpd_send_move_id(struct mpd_connection *connection, unsigned from, unsigned to); /** * Shortcut for mpd_send_move_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param from the source song id * @param to the new position of the song (not an id!) * @return true on success, false on error */ bool mpd_run_move_id(struct mpd_connection *connection, unsigned from, unsigned to); /** * Moves a song within the queue. * * @param connection the connection to MPD * @param from the source song id * @param to the new position of the song (not an id!) * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_send_move_id_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence); /** * Shortcut for mpd_send_move_id_whence() and mpd_response_finish(). * * @param connection the connection to MPD * @param from the source song id * @param to the new position of the song (not an id!) * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_run_move_id_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence); /** * Moves a range of songs within the queue. * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_send_move_range(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to); /** * Shortcut for mpd_send_move_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @return true on success, false on error * * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_run_move_range(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to); /** * Moves a range of songs within the queue. * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_send_move_range_whence(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence); /** * Shortcut for mpd_send_move_range_whence() and mpd_response_finish(). * * @param connection the connection to MPD * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @param to the new position of the song range * @param whence how to interpret the to parameter * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.23 */ bool mpd_run_move_range_whence(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence); /** * Swap the position of two songs in the queue. * * @param connection the connection to MPD * @param pos1 the position of one song * @param pos2 the position of the other song * @return true on success, false on error */ bool mpd_send_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2); /** * Shortcut for mpd_send_swap() and mpd_response_finish(). * * @param connection the connection to MPD * @param pos1 the position of one song * @param pos2 the position of the other song * @return true on success, false on error */ bool mpd_run_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2); /** * Swap the position of two songs in the queue. * * @param connection the connection to MPD * @param id1 the id of one song * @param id2 the id of the other song * @return true on success, false on error */ bool mpd_send_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2); /** * Shortcut for mpd_send_swap_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id1 the id of one song * @param id2 the id of the other song * @return true on success, false on error */ bool mpd_run_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2); /** * Adds a tag to the specified song (command "addtagid"). * * @param connection the connection to MPD * @param id the id of the song * @param tag the tag to be added * @param value the tag value * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_send_add_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag, const char *value); /** * Shortcut for mpd_send_add_tag_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id the id of the song * @param tag the tag to be added * @param value the tag value * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_run_add_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag, const char *value); /** * Remove a tag from the specified song (command "cleartagid"). * * @param connection the connection to MPD * @param id the id of the song * @param tag the tag to be cleared * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_send_clear_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag); /** * Shortcut for mpd_send_clear_tag_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id the id of the song * @param tag the tag to be cleared * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_run_clear_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag); /** * Remove all tags from the specified song (command "cleartagid"). * * @param connection the connection to MPD * @param id the id of the song * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_send_clear_all_tags_id(struct mpd_connection *connection, unsigned id); /** * Shortcut for mpd_send_clear_all_tags_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id the id of the song * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_run_clear_all_tags_id(struct mpd_connection *connection, unsigned id); /** * Change the priority of the specified song. * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param position the position of the song * @return true on success, false on error * * @since libmpdclient 2.6 */ bool mpd_send_prio(struct mpd_connection *connection, unsigned priority, unsigned position); /** * Shortcut for mpd_send_prio() and mpd_response_finish(). * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param position the position of the song * @return true on success, false on error * * @since libmpdclient 2.6 */ bool mpd_run_prio(struct mpd_connection *connection, unsigned priority, unsigned position); /** * Change the priority of a song range. * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.6 * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_send_prio_range(struct mpd_connection *connection, unsigned priority, unsigned start, unsigned end); /** * Shortcut for mpd_send_prio_range() and mpd_response_finish(). * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param start the start position of the range (including) * @param end the end position of the range (excluding); the special * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.6 * @since libmpdclient 2.8 added support for "UINT_MAX" */ bool mpd_run_prio_range(struct mpd_connection *connection, unsigned priority, unsigned start, unsigned end); /** * Change the priority of the specified song. * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param id the id of the song * @return true on success, false on error * * @since libmpdclient 2.6 */ bool mpd_send_prio_id(struct mpd_connection *connection, unsigned priority, unsigned id); /** * Shortcut for mpd_send_prio_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param priority a number between 0 and 255 * @param id the id of the song * @return true on success, false on error * * @since libmpdclient 2.6 */ bool mpd_run_prio_id(struct mpd_connection *connection, unsigned priority, unsigned id); /** * Specify the portion of a song that shall be played. * The song is identified by its id and cannot be the currently playing song. * * The start/end values are offsets in seconds (fractional seconds allowed); * both are optional. * * @param connection the connection to MPD * @param id the id of the song (cannot be the currently playing song) * @param start the offset in seconds for starting the song * @param end the offset in seconds for ending the song; a negative * value makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.19, MPD 0.20 */ bool mpd_send_range_id(struct mpd_connection *connection, unsigned id, float start, float end); /** * * Shortcut for mpd_send_range_id() and mpd_response_finish(). * * @param connection the connection to MPD * @param id the id of the song (cannot be the currently playing song) * @param start the offset in seconds for starting the song * @param end the offset in seconds for ending the song; a negative * value makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.19, MPD 0.20 */ bool mpd_run_range_id(struct mpd_connection *connection, unsigned id, float start, float end); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/readpicture.h000066400000000000000000000037621505242054600246330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_READPICTURE_H #define MPD_READPICTURE_H #include "compiler.h" #include #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sends the "readpicture" command to MPD. Call mpd_recv_readpicture() to * read response lines. * * @param connection a valid and connected #mpd_connection * @param uri the URI of the song * @param offset to read from * @return true on success * * @since libmpdclient 2.20, MPD 0.22 */ bool mpd_send_readpicture(struct mpd_connection *connection, const char *uri, unsigned offset); /** * Receives the "readpicture" response * * @param connection a valid and connected #mpd_connection * @param buffer an already allocated buffer, the size must be the same or greater than * the binary chunk size (default 8192, can be set with binarylimit command) * @param buffer_size the size of the allocated buffer * @return read size on success, -1 on failure * * @since libmpdclient 2.20, MPD 0.22 */ int mpd_recv_readpicture(struct mpd_connection *connection, void *buffer, size_t buffer_size); /** * Shortcut for mpd_send_readpicture(), mpd_recv_readpicture() and * mpd_response_finish(). * * @param connection a valid and connected #mpd_connection * @param uri the URI of the song * @param offset to read from * @param buffer an already allocated buffer, the size must be the same or greater than * the binary chunk size (default 8192, can be set with binarylimit command) * @param buffer_size the size of the allocated buffer * @return read size on success, -1 on failure * * @since libmpdclient 2.20, MPD 0.22 */ int mpd_run_readpicture(struct mpd_connection *connection, const char *uri, unsigned offset, void *buffer, size_t buffer_size); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/recv.h000066400000000000000000000034421505242054600232560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Receiving response lines from MPD. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_RECV_H #define MPD_RECV_H #include "compiler.h" #include #include struct mpd_pair; struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Reads the binary data response from the server. * The size and binary pair must be already read from the input buffer. * * The caller must allocate length bytes of memory for data. * * @return true on success * * @since libmpdclient 2.17 */ bool mpd_recv_binary(struct mpd_connection *connection, void *data, size_t length); /** * Reads the next #mpd_pair from the server. Returns NULL if there * are no more pairs. * * The caller must dispose the pair with either mpd_return_pair() or * mpd_enqueue_pair(). */ mpd_malloc struct mpd_pair * mpd_recv_pair(struct mpd_connection *connection); /** * Same as mpd_recv_pair(), but discards all pairs not matching the * specified name. */ mpd_malloc struct mpd_pair * mpd_recv_pair_named(struct mpd_connection *connection, const char *name); /** * Indicates that the pair object is not needed anymore, and can be * freed. You must free the previous #mpd_pair object before calling * mpd_recv_pair() again. */ void mpd_return_pair(struct mpd_connection *connection, struct mpd_pair *pair); /** * Unreads a #mpd_pair. You may unread only the one pair you just got * from mpd_recv_pair(). Unreading the "NULL" pair is allowed, to * allow you to call mpd_recv_pair() again at the end of a response. */ void mpd_enqueue_pair(struct mpd_connection *connection, struct mpd_pair *pair); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/replay_gain.h000066400000000000000000000062561505242054600246170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_REPLAY_GAIN_H #define MPD_REPLAY_GAIN_H #include "compiler.h" #include struct mpd_connection; /** * MPD's replay gain mode. * * @since libmpdclient 2.19, MPD 0.16. */ enum mpd_replay_gain_mode { /** ignore ReplayGain tag values */ MPD_REPLAY_OFF = 0, /** use per-track ReplayGain values */ MPD_REPLAY_TRACK, /** use per-album ReplayGain values */ MPD_REPLAY_ALBUM, /** * use available ReplayGain value; if both track and album tags are * available, prefer track values. **/ MPD_REPLAY_AUTO, /** Unknown mode */ MPD_REPLAY_UNKNOWN, }; #ifdef __cplusplus extern "C" { #endif /** * Parse a #mpd_pair value to check which replay gain mode it contains. */ mpd_pure enum mpd_replay_gain_mode mpd_parse_replay_gain_name(const char *name); /** * Looks up the name of the specified replay gain mode. * * @return the name, or NULL if the replay gain mode is not valid * * @since libmpdclient 2.19. */ mpd_pure const char * mpd_lookup_replay_gain_mode(enum mpd_replay_gain_mode mode); /** * Queries the current state of replay gain mode on MPD. * * Sends the "replay_gain_status" command to MPD. * Call mpd_recv_replay_gain_status() to read the response. * * @param connection the connection to MPD * @return true on success, false on error * * @since MPD 0.16, libmpdclient 2.19. */ bool mpd_send_replay_gain_status(struct mpd_connection *connection); /** * Receives the current state of replay gain mode on MPD. * Shortcut for mpd_recv_pair_named() and mpd_parse_replay_gain_name() ad * mpd_return_pair(). * * @param connection the connection to MPD * @return #mpd_replay_gain_mode object: #MPD_REPLAY_UNKNOWN on error (or * unknown ReplayGain mode); other modes on success. * * @since MPD 0.16, libmpdclient 2.21. */ enum mpd_replay_gain_mode mpd_recv_replay_gain_status(struct mpd_connection *connection); /** * Shortcut for mpd_send_replay_gain_status(), mpd_recv_replay_gain_status() and * mpd_response_finish(). * * @param connection the connection to MPD * @return #mpd_replay_gain_mode object: #MPD_REPLAY_UNKNOWN on error (or * unknown ReplayGain mode); other modes on success. * * @since MPD 0.16, libmpdclient 2.19. */ enum mpd_replay_gain_mode mpd_run_replay_gain_status(struct mpd_connection *connection); /** * Sets the current state of replay gain mode on MPD. * * @param connection the connection to MPD * @param mode the desired replay gain mode * @return true on success, false on error * * @since MPD 0.16, libmpdclient 2.19. */ bool mpd_send_replay_gain_mode(struct mpd_connection *connection, enum mpd_replay_gain_mode mode); /** * Shortcut for mpd_send_replay_gain_mode() and mpd_response_finish(). * * @param connection the connection to MPD * @param mode mode the desired replay gain mode * @return true on success, false on error * * @since MPD 0.16, libmpdclient 2.19. */ bool mpd_run_replay_gain_mode(struct mpd_connection *connection, enum mpd_replay_gain_mode mode); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/response.h000066400000000000000000000014751505242054600241610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_RESPONSE_H #define MPD_RESPONSE_H #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Finishes the response and checks if the command was successful. If * there are data pairs left, they are discarded. * * @return true on success, false on error */ bool mpd_response_finish(struct mpd_connection *connection); /** * Finishes the response of the current list command. If there are * data pairs left, they are discarded. * * @return true on success, false on error */ bool mpd_response_next(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/search.h000066400000000000000000000225611505242054600235670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Search songs in the database or the queue. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_SEARCH_H #define LIBMPDCLIENT_SEARCH_H #include "connection.h" #include "tag.h" #include "position.h" #include "compiler.h" #include #include /** * This type is not yet used, it is reserved for a future protocol * extension which will allow us to specify a comparison operator for * constraints. */ enum mpd_operator { /** * The default search operator. If "exact" was passed as * "true", then it means "full string comparison"; if false, * then it means "search for substring". */ MPD_OPERATOR_DEFAULT, }; #ifdef __cplusplus extern "C" { #endif /** * Search for songs in the database. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the search command with mpd_search_commit(), and read the * response items with mpd_recv_song(). * * @param connection the connection to MPD * @param exact if to match exact * @return true on success, false on error */ bool mpd_search_db_songs(struct mpd_connection *connection, bool exact); /** * Search for songs in the database and adds the result to the queue. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the search command with mpd_search_commit(). * * @param connection the connection to MPD * @param exact if to match exact (only "true" supported by MPD 0.16) * @return true on success, false on error */ bool mpd_search_add_db_songs(struct mpd_connection *connection, bool exact); /** * Search for songs in the database and adds the result to a playlist. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the search command with mpd_search_commit(). * * @param connection the connection to MPD * @param playlist_name the name of the playlist where songs shall be * added * @return true on success, false on error * * @since libmpdclient 2.17. */ bool mpd_search_add_db_songs_to_playlist(struct mpd_connection *connection, const char *playlist_name); /** * Search for songs in the queue. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the search command with mpd_search_commit(), and read the * response items with mpd_recv_song(). * * @param connection the connection to MPD * @param exact if to match exact * @return true on success, false on error */ bool mpd_search_queue_songs(struct mpd_connection *connection, bool exact); /** * Obtains a list of unique tag values from the database. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the search command with mpd_search_commit(), and read the * response items with mpd_recv_pair_tag(). * * @param connection the connection to MPD * @param type The type of the tags to search for * @return true on success, false on error */ bool mpd_search_db_tags(struct mpd_connection *connection, enum mpd_tag_type type); /** * Gathers statistics on a set of songs in the database. * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the command with mpd_search_commit(), and read the response * with mpd_recv_stats(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_count_db_songs(struct mpd_connection *connection); /** * Gathers statistics on a set of songs in the database. * This is the case insensitive variant of mpd_count_db_songs(). * Constraints may be specified with mpd_search_add_tag_constraint(). * Send the command with mpd_search_commit(), and read the response * with mpd_recv_stats(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_searchcount_db_songs(struct mpd_connection *connection); /** * Limit the search to a certain directory. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param value the URI relative to the music directory * @return true on success, false on error * * @since libmpdclient 2.9 */ bool mpd_search_add_base_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value); /** * Add a constraint on the song's URI. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param value The value of the constraint * @return true on success, false on error */ bool mpd_search_add_uri_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value); /** * Add a constraint to a search limiting the value of a tag. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param type The tag type of the constraint * @param value The value of the constraint * @return true on success, false on error */ bool mpd_search_add_tag_constraint(struct mpd_connection *connection, enum mpd_operator oper, enum mpd_tag_type type, const char *value); /** * Add a constraint to a search, search for a value in any tag. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param value The value of the constraint * @return true on success, false on error */ bool mpd_search_add_any_tag_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value); /** * Limit the search to files modified after the given time stamp. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param value the reference time stamp * @return true on success, false on error * * @since libmpdclient 2.10 */ bool mpd_search_add_modified_since_constraint(struct mpd_connection *connection, enum mpd_operator oper, time_t value); /** * Limit the search to files added after the given time stamp. * * @param connection a #mpd_connection * @param oper reserved, pass #MPD_OPERATOR_DEFAULT * @param value the reference time stamp * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.24 */ bool mpd_search_add_added_since_constraint(struct mpd_connection *connection, enum mpd_operator oper, time_t value); /** * Add an expression string. * * @param connection a #mpd_connection * @param expression the expression string; must be enclosed in * parentheses * @return true on success, false on error * * @since libmpdclient 2.15, MPD 0.21 */ bool mpd_search_add_expression(struct mpd_connection *connection, const char *expression); /** * Group the results by the specified tag. * * @param connection a #mpd_connection * @param type the tag type to group by * @return true on success, false on error * * @since libmpdclient 2.12, MPD 0.19 */ bool mpd_search_add_group_tag(struct mpd_connection *connection, enum mpd_tag_type type); /** * Sort the results by the specified named attribute. * * @param connection a #mpd_connection * @param name the attribute name to sort with; can be a tag name or * "Last-Modified" * @param descending sort in reverse order? * @return true on success, false on error * * @since MPD 0.21, libmpdclient 2.15 */ bool mpd_search_add_sort_name(struct mpd_connection *connection, const char *name, bool descending); /** * Sort the results by the specified tag. * * @param connection a #mpd_connection * @param type the tag type to sort with * @param descending sort in reverse order? * @return true on success, false on error * * @since MPD 0.21, libmpdclient 2.11; #descending since libmpdclient * 2.15 */ bool mpd_search_add_sort_tag(struct mpd_connection *connection, enum mpd_tag_type type, bool descending); /** * Request only a portion of the result set. * * @param connection a #mpd_connection * @param start the start offset (including) * @param end the end offset (not including) * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.10 */ bool mpd_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end); /** * Adds the search to the specified position in the queue. * * @param connection a #mpd_connection * @param position the position in the queue * @param whence how to interpret the position parameter * * @since libmpdclient 2.20 */ bool mpd_search_add_position(struct mpd_connection *connection, unsigned position, enum mpd_position_whence whence); /** * Starts the real search with constraints added with * mpd_search_add_constraint(). * * @param connection the connection to MPD * @return true on success, false on error */ bool mpd_search_commit(struct mpd_connection *connection); /** * Cancels the search request before you have called * mpd_search_commit(). Call this to clear the current search * request. * * @param connection the connection to MPD */ void mpd_search_cancel(struct mpd_connection *connection); /** * Same as mpd_recv_pair_named(), but the pair name is specified as * #mpd_tag_type. * * @param connection the connection to MPD * @param type the tag type you are looking for * @return a pair, or NULL on error or if there are no more matching * pairs in this response */ mpd_malloc struct mpd_pair * mpd_recv_pair_tag(struct mpd_connection *connection, enum mpd_tag_type type); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/send.h000066400000000000000000000013451505242054600232500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_SEND_H #define LIBMPDCLIENT_SEND_H #include "compiler.h" #include struct mpd_connection; #ifdef __cplusplus extern "C" { #endif /** * Sends a command with arguments to the MPD server. The argument * list must be terminated with a NULL. * * @param connection the connection to the MPD server * @param command the command to be sent * @return true on success */ mpd_sentinel bool mpd_send_command(struct mpd_connection *connection, const char *command, ...); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/settings.h000066400000000000000000000046461505242054600241660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Library to determine connection settings prior to calling * mpd_connection_new(). * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_SETTINGS_H #define MPD_SETTINGS_H #include /** * \struct mpd_settings * * An object which describes configurable connection settings. */ struct mpd_settings; #ifdef __cplusplus extern "C" { #endif /** * Creates a new #mpd_settings object. The values which are not * passed by the caller are taken from environment variables. * * @param host the server's host name, IP address or Unix socket path. * An address starting with '@' denotes an "abstract socket". * NULL is allowed here, which will connect to the default host * (using the MPD_HOST environment variable if present). * @param port the TCP port to connect to, 0 for default port (using * the MPD_PORT environment variable if present). If "host" is a Unix * socket path, this parameter is ignored. * @param timeout_ms the timeout in milliseconds, 0 for the default * timeout (the environment variable MPD_TIMEOUT may specify a timeout * in seconds) * @param reserved reserved for future use, pass NULL * @param password the password, or NULL to use the default (MPD_HOST * before "@") * @return a #mpd_settings object or NULL if out of memory * * @since libmpdclient 2.4 */ struct mpd_settings * mpd_settings_new(const char *host, unsigned port, unsigned timeout_ms, const char *reserved, const char *password); /** * Releases a #mpd_settings object. * * @since libmpdclient 2.4 */ void mpd_settings_free(struct mpd_settings *settings); /** * Returns the host name (without password/port), or NULL if unknown. * * @since libmpdclient 2.4 */ const char * mpd_settings_get_host(const struct mpd_settings *settings); /** * Returns the port number, or 0 if not applicable. * * @since libmpdclient 2.4 */ unsigned mpd_settings_get_port(const struct mpd_settings *settings); /** * Returns the timeout in milliseconds, or 0 if unknown. * * @since libmpdclient 2.4 */ unsigned mpd_settings_get_timeout_ms(const struct mpd_settings *settings); /** * Returns the password, or NULL if none was configured. * * @since libmpdclient 2.4 */ const char * mpd_settings_get_password(const struct mpd_settings *settings); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/socket.h000066400000000000000000000006751505242054600236140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef LIBMPDCLIENT_SOCKET_H #define LIBMPDCLIENT_SOCKET_H #ifdef WIN32 #include typedef SOCKET mpd_socket_t; #define MPD_INVALID_SOCKET INVALID_SOCKET #else typedef int mpd_socket_t; #define MPD_INVALID_SOCKET -1 #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/song.h000066400000000000000000000112741505242054600232670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_SONG_H #define MPD_SONG_H #include "tag.h" #include "compiler.h" #include #include struct mpd_pair; struct mpd_connection; /** * \struct mpd_song * * An opaque representation for a song in MPD's database or playlist. * Use the functions provided by this header to access the object's * attributes. */ struct mpd_song; #ifdef __cplusplus extern "C" { #endif /** * Free memory allocated by the #mpd_song object. */ void mpd_song_free(struct mpd_song *song); /** * Duplicates the specified #mpd_song object. * * @returns the copy, or NULL if out of memory */ mpd_malloc struct mpd_song * mpd_song_dup(const struct mpd_song *song); /** * Returns the URI of the song. This is either a path relative to the * MPD music directory (without leading slash), or an URL with a * scheme, e.g. a HTTP URL for a radio stream. */ mpd_pure const char * mpd_song_get_uri(const struct mpd_song *song); /** * Queries a tag value. * * @param song the song object * @param type the tag type * @param idx pass 0 to get the first value for this tag type. This * argument may be used to iterate all values, until this function * returns NULL * @return the tag value, or NULL if this tag type (or this index) * does not exist */ mpd_pure const char * mpd_song_get_tag(const struct mpd_song *song, enum mpd_tag_type type, unsigned idx); /** * Returns the duration of this song in seconds. 0 means the duration * is unknown. */ mpd_pure unsigned mpd_song_get_duration(const struct mpd_song *song); /** * Returns the duration of this song in milliseconds. 0 means the * duration is unknown. * * @since libmpdclient 2.10 */ mpd_pure unsigned mpd_song_get_duration_ms(const struct mpd_song *song); /** * Returns the start of the virtual song within the physical file in * seconds. * * @since libmpdclient 2.3 */ mpd_pure unsigned mpd_song_get_start(const struct mpd_song *song); /** * Returns the end of the virtual song within the physical file in * seconds. 0 means that the physical song file is played to the end. * * @since libmpdclient 2.3 */ mpd_pure unsigned mpd_song_get_end(const struct mpd_song *song); /** * @return the POSIX UTC time stamp of the last modification, or 0 if * that is unknown */ mpd_pure time_t mpd_song_get_last_modified(const struct mpd_song *song); /** * @return the POSIX UTC time stamp of database addition, or 0 if * that is unknown. * * @since libmpdclient 2.21, MPD 0.24 */ mpd_pure time_t mpd_song_get_added(const struct mpd_song *song); /** * Sets the position within the queue. This value is not used for * songs which are not in the queue. * * This function is useful when applying the values returned by * mpd_recv_queue_change_brief(). */ void mpd_song_set_pos(struct mpd_song *song, unsigned pos); /** * Returns the position of this song in the queue. The value is * undefined if you did not obtain this song from the queue. */ mpd_pure unsigned mpd_song_get_pos(const struct mpd_song *song); /** * Returns the id of this song in the playlist. The value is * undefined if you did not obtain this song from the queue. */ mpd_pure unsigned mpd_song_get_id(const struct mpd_song *song); /** * Returns the priority of this song in the playlist. The value is * undefined if you did not obtain this song from the queue. * * @since libmpdclient 2.8 */ mpd_pure unsigned mpd_song_get_prio(const struct mpd_song *song); /** * Returns audio format as determined by MPD's decoder plugin. May * return NULL if the format is not available or unknown. * * @since libmpdclient 2.15 */ mpd_pure const struct mpd_audio_format * mpd_song_get_audio_format(const struct mpd_song *song); /** * Begins parsing a new song. * * @param pair the first pair in this song (name must be "file") * @return the new #mpd_entity object, or NULL on error (out of * memory, or pair name is not "file") */ mpd_malloc struct mpd_song * mpd_song_begin(const struct mpd_pair *pair); /** * Parses the pair, adding its information to the specified * #mpd_song object. * * @return true if the pair was parsed and added to the song (or if * the pair was not understood and ignored), false if this pair is the * beginning of the next song */ bool mpd_song_feed(struct mpd_song *song, const struct mpd_pair *pair); /** * Receives the next song from the MPD server. * * @return a #mpd_song object, or NULL on error or if the song list is * finished */ mpd_malloc struct mpd_song * mpd_recv_song(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/stats.h000066400000000000000000000053261505242054600234600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_STATS_H #define MPD_STATS_H #include "compiler.h" #include struct mpd_connection; struct mpd_pair; /** * \struct mpd_stats * * An opaque object representing MPD's response to the "stats" * command. To release this object, call mpd_stats_free(). */ struct mpd_stats; #ifdef __cplusplus extern "C" { #endif /** * Send the "stats" command to MPD. Call mpd_recv_stats() to read the response. * * @return true on success */ bool mpd_send_stats(struct mpd_connection *connection); /** * Begins parsing server stats: creates a new empty #mpd_stats object. * Free it with mpd_stats_free(). * * @return the newly allocated #mpd_stats object, or NULL if out of * memory */ mpd_malloc struct mpd_stats * mpd_stats_begin(void); /** * Parses the pair, adding its information to the specified #mpd_stats * object. */ void mpd_stats_feed(struct mpd_stats *stats, const struct mpd_pair *pair); /** * Reads the "stats" response from MPD. * * @return a #mpd_stats object, or NULL on error */ mpd_malloc struct mpd_stats * mpd_recv_stats(struct mpd_connection *connection); /** * Shortcut for mpd_send_stats() and mpd_recv_stats(). */ mpd_malloc struct mpd_stats * mpd_run_stats(struct mpd_connection *connection); /** * Frees a #mpd_stats object. */ void mpd_stats_free(struct mpd_stats *stats); /** * @return the number of distinct artists in MPD's database, or 0 if * unknown */ mpd_pure unsigned mpd_stats_get_number_of_artists(const struct mpd_stats *stats); /** * @return the number of distinct album names in MPD's database, or 0 * if unknown */ mpd_pure unsigned mpd_stats_get_number_of_albums(const struct mpd_stats *stats); /** * @return the total number of song files in MPD's database, or 0 if * unknown */ mpd_pure unsigned mpd_stats_get_number_of_songs(const struct mpd_stats *stats); /** * @return the uptime of MPD in seconds, or 0 if unknown */ mpd_pure unsigned long mpd_stats_get_uptime(const struct mpd_stats *stats); /** * @return the UNIX time stamp of the last database update, or 0 if * unknown */ mpd_pure unsigned long mpd_stats_get_db_update_time(const struct mpd_stats *stats); /** * @return the accumulated time MPD was playing music since the * process was started, or 0 if unknown */ mpd_pure unsigned long mpd_stats_get_play_time(const struct mpd_stats *stats); /** * @return the accumulated duration of all songs in the database, or 0 * if unknown */ mpd_pure unsigned long mpd_stats_get_db_play_time(const struct mpd_stats *stats); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/status.h000066400000000000000000000215531505242054600236450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_STATUS_H #define MPD_STATUS_H #include "compiler.h" #include /** * MPD's playback state. */ enum mpd_state { /** no information available */ MPD_STATE_UNKNOWN = 0, /** not playing */ MPD_STATE_STOP = 1, /** playing */ MPD_STATE_PLAY = 2, /** playing, but paused */ MPD_STATE_PAUSE = 3, }; /** * MPD's single state. * * @since libmpdclient 2.18, MPD 0.21. */ enum mpd_single_state { /** disabled */ MPD_SINGLE_OFF = 0, /** enabled */ MPD_SINGLE_ON, /** * enables single state (#MPD_SINGLE_ONESHOT) for a single song, then * MPD disables single state (#MPD_SINGLE_OFF) if the current song * has played and there is another song in the current playlist * * @since MPD 0.21 **/ MPD_SINGLE_ONESHOT, /** Unknown state */ MPD_SINGLE_UNKNOWN, }; /** * MPD's consume state. * * @since libmpdclient 2.21, MPD 0.24. */ enum mpd_consume_state { /** disabled */ MPD_CONSUME_OFF = 0, /** enabled */ MPD_CONSUME_ON, /** * enables consume state (#MPD_CONSUME_ONESHOT) for a single song, then * MPD disables consume state (#MPD_CONSUME_OFF) if the current song * has played. * * @since MPD 0.24 **/ MPD_CONSUME_ONESHOT, /** Unknown state */ MPD_CONSUME_UNKNOWN, }; struct mpd_connection; struct mpd_pair; struct mpd_audio_format; /** * \struct mpd_status * * Holds information about MPD's status. */ struct mpd_status; #ifdef __cplusplus extern "C" { #endif /** * Begins parsing the server status: creates a new empty #mpd_status * object. Free it with mpd_status_free(). * * @return the newly allocated #mpd_status object, or NULL if out of * memory */ mpd_malloc struct mpd_status * mpd_status_begin(void); /** * Parses the pair, adding its information to the specified * #mpd_status object. */ void mpd_status_feed(struct mpd_status *status, const struct mpd_pair *pair); /** * Sends the "status" command to MPD. Call mpd_recv_status() to read * the response. * * @return true on success */ bool mpd_send_status(struct mpd_connection *connection); /** * Receives a #mpd_status object from the server. * * @return the received #mpd_status object, or NULL on error */ mpd_malloc struct mpd_status * mpd_recv_status(struct mpd_connection *connection); /** * Executes the "status" command and reads the response. * * @return the #mpd_status object returned by the server, or NULL on * error */ mpd_malloc struct mpd_status * mpd_run_status(struct mpd_connection *connection); /** * Releases a #mpd_status object. */ void mpd_status_free(struct mpd_status * status); /** * Returns the current volume: 0-100, or -1 when there is no volume * support. */ mpd_pure int mpd_status_get_volume(const struct mpd_status *status); /** * Returns true if repeat mode is on. */ mpd_pure bool mpd_status_get_repeat(const struct mpd_status *status); /** * Returns true if random mode is on. */ mpd_pure bool mpd_status_get_random(const struct mpd_status *status); /** * Returns the current state of single mode on MPD. * * If the state is #MPD_SINGLE_ONESHOT, MPD will transition to #MPD_SINGLE_OFF * after a song is played and if there is another song in the queue. The * #mpd_status object will not be updated accordingly. In this case, you need * to call mpd_send_status() and mpd_recv_status() again. * * @since MPD 0.21, libmpdclient 2.18. */ mpd_pure enum mpd_single_state mpd_status_get_single_state(const struct mpd_status *status); /** * Looks up the name of the specified single mode. * * @return the name, or NULL if the single mode is not valid * * @since libmpdclient 2.21. */ const char * mpd_lookup_single_state(enum mpd_single_state state); /** * Parse the string to check which single mode it contains. * * @return the single mode enum * * @since libmpdclient 2.21. */ enum mpd_single_state mpd_parse_single_state(const char *p); /** * This function is deprecated as it does not distinguish the states of * the single mode (added to MPD 0.21). Call mpd_status_get_single_state() in * its place. * * Returns true if single mode is either on or in oneshot. */ mpd_pure bool mpd_status_get_single(const struct mpd_status *status); /** * Returns the current state of consume mode on MPD. * * If the state is #MPD_CONSUME_ONESHOT, MPD will transition to #MPD_CONSUME_OFF * after a song is played. The #mpd_status object will not be updated accordingly. * In this case, you need to call mpd_send_status() and mpd_recv_status() again. * * @since MPD 0.24, libmpdclient 2.21. */ mpd_pure enum mpd_consume_state mpd_status_get_consume_state(const struct mpd_status *status); /** * Looks up the name of the specified consume mode. * * @return the name, or NULL if the consume mode is not valid * * @since libmpdclient 2.21. */ const char * mpd_lookup_consume_state(enum mpd_consume_state state); /** * Parse the string to check which consume mode it contains. * * @return the consume mode enum * * @since libmpdclient 2.21. */ enum mpd_consume_state mpd_parse_consume_state(const char *p); /** * This function is deprecated as it does not distinguish the states of * the consume mode (added to MPD 0.24). Call mpd_status_get_consume_state() in * its place. * * Returns true if consume mode is either on or in oneshot. */ mpd_pure bool mpd_status_get_consume(const struct mpd_status *status); /** * Returns the number of songs in the queue. If MPD did not * specify that, this function returns 0. */ mpd_pure unsigned mpd_status_get_queue_length(const struct mpd_status *status); /** * Returns queue version number. You may use this to determine * when the queue has changed since you have last queried it. */ mpd_pure unsigned mpd_status_get_queue_version(const struct mpd_status *status); /** * Returns the state of the player: either stopped, playing or paused. */ mpd_pure enum mpd_state mpd_status_get_state(const struct mpd_status *status); /** * Returns crossfade setting in seconds. 0 means crossfading is * disabled. */ mpd_pure unsigned mpd_status_get_crossfade(const struct mpd_status *status); /** * Returns mixrampdb setting in db. 0 means mixrampdb is disabled. * * @since libmpdclient 2.2 */ mpd_pure float mpd_status_get_mixrampdb(const struct mpd_status *status); /** * Returns mixrampdelay setting in seconds. Negative means mixrampdelay is * disabled. * * @since libmpdclient 2.2 */ mpd_pure float mpd_status_get_mixrampdelay(const struct mpd_status *status); /** * Returns the position of the currently playing song in the queue * (beginning with 0) if a song is currently selected (always the case when * state is MPD_STATE_PLAY or MPD_STATE_PAUSE). If there is no current song, * -1 is returned. */ mpd_pure int mpd_status_get_song_pos(const struct mpd_status *status); /** * Returns the id of the current song. If there is no current song, * -1 is returned. */ mpd_pure int mpd_status_get_song_id(const struct mpd_status *status); /** * The same as mpd_status_get_song_pos(), but for the next song to be * played. * * @since libmpdclient 2.7 */ mpd_pure int mpd_status_get_next_song_pos(const struct mpd_status *status); /** * Returns the id of the next song to be played. If it is not known, -1 is * returned. * * @since libmpdclient 2.7 */ mpd_pure int mpd_status_get_next_song_id(const struct mpd_status *status); /** * This function uses a deprecated feature of MPD, call * mpd_status_get_elapsed_ms() instead. * * Returns time in seconds that have elapsed in the currently playing/paused * song. * */ mpd_pure unsigned mpd_status_get_elapsed_time(const struct mpd_status *status); /** * Returns time in milliseconds that have elapsed in the currently * playing/paused song. * * @since libmpdclient 2.1 */ mpd_pure unsigned mpd_status_get_elapsed_ms(const struct mpd_status *status); /** * Returns the length in seconds of the currently playing/paused song */ mpd_pure unsigned mpd_status_get_total_time(const struct mpd_status *status); /** * Returns current bit rate in kbps. 0 means unknown. */ mpd_pure unsigned mpd_status_get_kbit_rate(const struct mpd_status *status); /** * Returns audio format which MPD is currently playing. May return * NULL if MPD is not playing or if the audio format is unknown. */ mpd_pure const struct mpd_audio_format * mpd_status_get_audio_format(const struct mpd_status *status); /** * Returns 1 if mpd is updating, 0 otherwise */ mpd_pure unsigned mpd_status_get_update_id(const struct mpd_status *status); /** * Returns the name of the current partition or NULL if the server did * not send a name. */ mpd_pure const char * mpd_status_get_partition(const struct mpd_status *status); /** * Returns the error message */ mpd_pure const char * mpd_status_get_error(const struct mpd_status *status); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/sticker.h000066400000000000000000000261631505242054600237700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Manipulate stickers. * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_STICKER_H #define MPD_STICKER_H #include "compiler.h" #include #include struct mpd_connection; /** * Comparison operators for sticker search api */ enum mpd_sticker_operator { MPD_STICKER_OP_UNKOWN = -1, MPD_STICKER_OP_EQ, MPD_STICKER_OP_GT, MPD_STICKER_OP_LT, MPD_STICKER_OP_EQ_INT, MPD_STICKER_OP_GT_INT, MPD_STICKER_OP_LT_INT, MPD_STICKER_OP_CONTAINS, MPD_STICKER_OP_STARTS_WITH, }; /** * Sort by settings for sticker search api */ enum mpd_sticker_sort { MPD_STICKER_SORT_UNKOWN = -1, MPD_STICKER_SORT_URI, MPD_STICKER_SORT_VALUE, MPD_STICKER_SORT_VALUE_INT, }; #ifdef __cplusplus extern "C" { #endif /** * Stickers are pieces of information attached to existing MPD objects (e.g. * song files, directories, albums; but currently, they are only implemented * for song). Clients can create arbitrary name/value pairs. MPD itself does * not assume any special meaning in them. * * The goal is to allow clients to share additional (possibly dynamic) * information about songs, which is neither stored on the client (not * available to other clients), nor stored in the song files (MPD has no write * access). * * Client developers should create a standard for common sticker names, to * ensure interoperability. * * Objects which may have stickers are addressed by their object type ("song" * for song objects) and their URI (the path within the database for songs). */ /** * Adds or replaces a sticker value. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the value of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_send_sticker_set(struct mpd_connection *connection, const char *type, const char *uri, const char *name, const char *value); /** * Shortcut for mpd_send_sticker_set() and mpd_response_finish(). * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the value of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_run_sticker_set(struct mpd_connection *connection, const char *type, const char *uri, const char *name, const char *value); /** * Adds or increments a sticker value. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the unsigned value to set or increment * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_sticker_inc(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value); /** * Shortcut for mpd_send_sticker_inc() and mpd_response_finish(). * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the unsigned value to set or increment * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_sticker_inc(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value); /** * Adds or decrements a sticker value. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the unsigned value to set or increment * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_sticker_dec(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value); /** * Shortcut for mpd_send_sticker_dec() and mpd_response_finish(). * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @param value the unsigned value to set or increment * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_run_sticker_dec(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value); /** * Deletes a sticker value. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_send_sticker_delete(struct mpd_connection *connection, const char *type, const char *uri, const char *name); /** * Shortcut for mpd_send_sticker_delete() and mpd_response_finish(). * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_run_sticker_delete(struct mpd_connection *connection, const char *type, const char *uri, const char *name); /** * Queries a sticker value. Call mpd_recv_sticker() to receive the response. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @param name the name of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_send_sticker_get(struct mpd_connection *connection, const char *type, const char *uri, const char *name); /** * Obtains a list of all stickers of the specified object. Call * mpd_recv_sticker() to receive each response item. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param uri the URI of the object * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_send_sticker_list(struct mpd_connection *connection, const char *type, const char *uri); /** * Searches for stickers with the specified name. Call mpd_recv_sticker() to * receive each response item. * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param base_uri the base URI to start the search, e.g. a directory; * NULL to search for all objects of the specified type * @param name the name of the sticker * @return true on success, false on error * * @since libmpdclient 2.1 */ bool mpd_send_sticker_find(struct mpd_connection *connection, const char *type, const char *base_uri, const char *name); /** * Parse a sticker input line in the form "name=value". * * @param input the input value, the value from a received pair named * "sticker" * @param name_length_r the length of the name (starting at the * beginning of the input string) is returned here * @return a pointer to the sticker value, or NULL on error * * @since libmpdclient 2.1 */ const char * mpd_parse_sticker(const char *input, size_t *name_length_r); /** * Receives the next sticker. You have to free the return value with * mpd_return_sticker(). * * @param connection the connection to MPD * @return a #mpd_pair object on success, NULL on end of response or * error * * @since libmpdclient 2.1 */ mpd_malloc struct mpd_pair * mpd_recv_sticker(struct mpd_connection *connection); /** * Free the pair returned by mpd_recv_sticker(). * * @since libmpdclient 2.1 */ void mpd_return_sticker(struct mpd_connection *connection, struct mpd_pair *pair); /** * Obtains an uniq and sorted list of all sticker names. Call * mpd_recv_pair() to receive each response item. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.21, MPD 0.24 */ bool mpd_send_stickernames(struct mpd_connection *connection); /** * Obtains an uniq list of all sticker types. Call * mpd_recv_pair() to receive each response item. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 * */ bool mpd_send_stickertypes(struct mpd_connection *connection); /** * Obtains an uniq and sorted list of all sticker names and their types. Call * mpd_recv_pair() to receive each response item. * * @param connection the connection to MPD * @param type the object type, e.g. "song" or NULL for all types * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_send_stickernamestypes(struct mpd_connection *connection, const char *type); /** * Search for stickers in the database. * Constraints may be specified. * Send the search command with mpd_sticker_search_commit(), and read the * response items with mpd_recv_sticker(). * * @param connection the connection to MPD * @param type the object type, e.g. "song" * @param base_uri the base URI to start the search, e.g. a directory; * NULL to search for all objects of the specified type * @param name the name of the sticker * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_sticker_search_begin(struct mpd_connection *connection, const char *type, const char *base_uri, const char *name); /** * Adds the value constraint to the search * @param connection a #mpd_connection * @param oper compare operator * @param value value to compare against * @return true on success, else false * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_sticker_search_add_value_constraint(struct mpd_connection *connection, enum mpd_sticker_operator oper, const char *value); /** * Sort the results by the specified named attribute. * * @param connection a #mpd_connection * @param sort sort by field * @param descending sort in reverse order? * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_sticker_search_add_sort(struct mpd_connection *connection, enum mpd_sticker_sort sort, bool descending); /** * Request only a portion of the result set. * * @param connection a #mpd_connection * @param start the start offset (including) * @param end the end offset (not including) * value "UINT_MAX" makes the end of the range open * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_sticker_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end); /** * Starts the real search. * * @param connection the connection to MPD * @return true on success, false on error * * @since libmpdclient 2.23, MPD 0.24 */ bool mpd_sticker_search_commit(struct mpd_connection *connection); /** * Cancels the search request before you have called * mpd_sticker_search_commit(). Call this to clear the current search * request. * * @param connection the connection to MPD * * @since libmpdclient 2.23, MPD 0.24 */ void mpd_sticker_search_cancel(struct mpd_connection *connection); #ifdef __cplusplus } #endif #endif /* MPD_STICKER_H */ MusicPlayerDaemon-libmpdclient-5073329/include/mpd/stringnormalization.h000066400000000000000000000117431505242054600264370ustar00rootroot00000000000000// 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 MusicPlayerDaemon-libmpdclient-5073329/include/mpd/tag.h000066400000000000000000000055751505242054600231030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #ifndef LIBMPDCLIENT_TAG_H #define LIBMPDCLIENT_TAG_H /** * @since libmpdclient 2.10 added support for #MPD_TAG_MUSICBRAINZ_RELEASETRACKID. * @since libmpdclient 2.11 added support for #MPD_TAG_ARTIST_SORT, * #MPD_TAG_ALBUM_ARTIST_SORT. * @since libmpdclient 2.17 added support for #MPD_TAG_LABEL, * #MPD_TAG_MUSICBRAINZ_WORKID, * #MPD_TAG_GROUPING, * #MPD_TAG_WORK, * #MPD_TAG_CONDUCTOR. * @since libmpdclient 2.20 added support for #MPD_TAG_COMPOSER_SORT, * #MPD_TAG_ENSEMBLE, * #MPD_TAG_MOVEMENT, * #MPD_TAG_MOVEMENTNUMBER, * #MPD_TAG_LOCATION. * @since libmpdclient 2.21 added support for #MPD_TAG_MOOD, * #MPD_TAG_TITLE_SORT. * @since libmpdclient 2.23 added support for #MPD_TAG_SHOWMOVEMENT. */ enum mpd_tag_type { /** * Special value returned by mpd_tag_name_parse() when an * unknown name was passed. */ MPD_TAG_UNKNOWN = -1, MPD_TAG_ARTIST, MPD_TAG_ALBUM, MPD_TAG_ALBUM_ARTIST, MPD_TAG_TITLE, MPD_TAG_TRACK, MPD_TAG_NAME, MPD_TAG_GENRE, MPD_TAG_DATE, MPD_TAG_COMPOSER, MPD_TAG_PERFORMER, MPD_TAG_COMMENT, MPD_TAG_DISC, MPD_TAG_MUSICBRAINZ_ARTISTID, MPD_TAG_MUSICBRAINZ_ALBUMID, MPD_TAG_MUSICBRAINZ_ALBUMARTISTID, MPD_TAG_MUSICBRAINZ_TRACKID, MPD_TAG_MUSICBRAINZ_RELEASETRACKID, MPD_TAG_ORIGINAL_DATE, MPD_TAG_ARTIST_SORT, MPD_TAG_ALBUM_ARTIST_SORT, MPD_TAG_ALBUM_SORT, MPD_TAG_LABEL, MPD_TAG_MUSICBRAINZ_WORKID, MPD_TAG_GROUPING, MPD_TAG_WORK, MPD_TAG_CONDUCTOR, MPD_TAG_COMPOSER_SORT, MPD_TAG_ENSEMBLE, MPD_TAG_MOVEMENT, MPD_TAG_MOVEMENTNUMBER, MPD_TAG_LOCATION, MPD_TAG_MOOD, MPD_TAG_TITLE_SORT, MPD_TAG_MUSICBRAINZ_RELEASEGROUPID, MPD_TAG_SHOWMOVEMENT, /* IMPORTANT: the ordering of tag types above must be retained, or else the libmpdclient ABI breaks */ MPD_TAG_COUNT }; #ifdef __cplusplus extern "C" { #endif /** * Looks up the name of the specified tag. * * @return the name, or NULL if the tag type is not valid */ const char * mpd_tag_name(enum mpd_tag_type type); /** * Parses a tag name, and returns its #mpd_tag_type value. * * @return a #mpd_tag_type value, or MPD_TAG_UNKNOWN if the name was * not recognized */ enum mpd_tag_type mpd_tag_name_parse(const char *name); /** * Same as mpd_tag_name_parse(), but ignores case. * * @return a #mpd_tag_type value, or MPD_TAG_UNKNOWN if the name was * not recognized */ enum mpd_tag_type mpd_tag_name_iparse(const char *name); #ifdef __cplusplus } #endif #endif MusicPlayerDaemon-libmpdclient-5073329/include/mpd/version.h.in000066400000000000000000000017341505242054600244130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief MPD client library * * Do not include this header directly. Use mpd/client.h instead. */ #ifndef MPD_VERSION_H #define MPD_VERSION_H #define LIBMPDCLIENT_MAJOR_VERSION @MAJOR_VERSION@ #define LIBMPDCLIENT_MINOR_VERSION @MINOR_VERSION@ #define LIBMPDCLIENT_PATCH_VERSION @PATCH_VERSION@ /** * Preprocessor macro which allows you to check which version of * libmpdclient you are compiling with. It can be used in * preprocessor directives. * * @return true if this libmpdclient version equals or is newer than * the specified version number * @since libmpdclient 2.1 */ #define LIBMPDCLIENT_CHECK_VERSION(major, minor, patch) \ ((major) < LIBMPDCLIENT_MAJOR_VERSION || \ ((major) == LIBMPDCLIENT_MAJOR_VERSION && \ ((minor) < LIBMPDCLIENT_MINOR_VERSION || \ ((minor) == LIBMPDCLIENT_MINOR_VERSION && \ (patch) <= LIBMPDCLIENT_PATCH_VERSION)))) #endif MusicPlayerDaemon-libmpdclient-5073329/libmpdclient.ld000066400000000000000000000305231505242054600227320ustar00rootroot00000000000000libmpdclient2 { global: /* mpd/async.h */ mpd_async_new; mpd_async_free; mpd_async_get_error; mpd_async_get_error_message; mpd_async_get_system_error; mpd_async_get_fd; mpd_async_set_keepalive; mpd_async_events; mpd_async_io; mpd_async_send_command_v; mpd_async_send_command; mpd_async_recv_line; mpd_async_recv_raw; /* mpd/capabilities.h */ mpd_send_allowed_commands; mpd_send_disallowed_commands; mpd_send_list_url_schemes; mpd_send_list_tag_types; mpd_send_list_tag_types_available; mpd_send_disable_tag_types; mpd_run_disable_tag_types; mpd_send_enable_tag_types; mpd_run_enable_tag_types; mpd_send_clear_tag_types; mpd_run_clear_tag_types; mpd_send_all_tag_types; mpd_run_all_tag_types; mpd_send_reset_tag_types; mpd_run_reset_tag_types; mpd_send_list_protocol_features; mpd_send_list_protocol_features_available; mpd_send_disable_protocol_features; mpd_run_disable_protocol_features; mpd_send_enable_protocol_features; mpd_run_enable_protocol_features; mpd_send_clear_protocol_features; mpd_run_clear_protocol_features; mpd_send_all_protocol_features; mpd_run_all_protocol_features; /* mpd/connection.h */ mpd_connection_new; mpd_connection_new_async; mpd_connection_free; mpd_connection_set_keepalive; mpd_connection_get_settings; mpd_connection_set_timeout; mpd_connection_get_fd; mpd_connection_get_async; mpd_connection_get_error; mpd_connection_get_error_message; mpd_connection_get_server_error; mpd_connection_get_server_error_location; mpd_connection_get_system_error; mpd_connection_clear_error; mpd_connection_get_server_version; mpd_connection_cmp_server_version; /* mpd/database.h */ mpd_send_list_all; mpd_send_list_all_meta; mpd_send_list_meta; mpd_send_list_files; mpd_send_read_comments; mpd_send_update; mpd_send_rescan; mpd_recv_update_id; mpd_run_update; mpd_run_rescan; /* mpd/directory.h */ mpd_directory_dup; mpd_directory_free; mpd_directory_get_path; mpd_directory_get_last_modified; mpd_directory_begin; mpd_directory_feed; mpd_recv_directory; /* mpd/entity.h */ mpd_entity_free; mpd_entity_get_type; mpd_entity_get_directory; mpd_entity_get_song; mpd_entity_get_playlist; mpd_entity_begin; mpd_entity_feed; mpd_recv_entity; /* mpd/feature.h */ mpd_feature_name; mpd_feature_name_parse; /* mpd/idle.h */ mpd_idle_name; mpd_idle_name_parse; mpd_send_idle; mpd_send_idle_mask; mpd_send_noidle; mpd_idle_parse_pair; mpd_recv_idle; mpd_run_idle; mpd_run_idle_mask; mpd_run_noidle; /* mpd/list.h */ mpd_command_list_begin; mpd_command_list_end; /* mpd/message.h */ mpd_message_begin; mpd_message_feed; mpd_message_free; mpd_message_get_channel; mpd_message_get_text; mpd_send_subscribe; mpd_run_subscribe; mpd_send_unsubscribe; mpd_run_unsubscribe; mpd_send_send_message; mpd_run_send_message; mpd_send_read_messages; mpd_recv_message; mpd_send_channels; /* mpd/mixer.h */ mpd_send_set_volume; mpd_run_set_volume; mpd_send_change_volume; mpd_run_change_volume; mpd_send_get_volume; mpd_run_get_volume; /* mpd/mount.h */ mpd_mount_begin; mpd_mount_feed; mpd_mount_free; mpd_mount_get_uri; mpd_mount_get_storage; mpd_send_list_mounts; mpd_recv_mount; mpd_send_mount; mpd_run_mount; mpd_send_unmount; mpd_run_unmount; /* mpd/neighbor.h */ mpd_neighbor_begin; mpd_neighbor_feed; mpd_neighbor_free; mpd_neighbor_get_uri; mpd_neighbor_get_display_name; mpd_send_list_neighbors; mpd_recv_neighbor; /* mpd/output.h */ mpd_output_begin; mpd_output_feed; mpd_output_free; mpd_output_get_id; mpd_output_get_name; mpd_output_get_plugin; mpd_output_get_enabled; mpd_output_get_attribute; mpd_output_first_attribute; mpd_output_next_attribute; mpd_send_outputs; mpd_recv_output; mpd_send_enable_output; mpd_run_enable_output; mpd_send_disable_output; mpd_run_disable_output; mpd_send_toggle_output; mpd_run_toggle_output; mpd_send_output_set; mpd_run_output_set; mpd_send_move_output; mpd_run_move_output; /* mpd/parser.h */ mpd_parser_new; mpd_parser_free; mpd_parser_feed; mpd_parser_is_discrete; mpd_parser_get_server_error; mpd_parser_get_at; mpd_parser_get_message; mpd_parser_get_name; mpd_parser_get_value; /* mpd/password.h */ mpd_send_password; mpd_run_password; /* mpd/player.h */ mpd_send_current_song; mpd_run_current_song; mpd_send_play; mpd_run_play; mpd_send_play_pos; mpd_run_play_pos; mpd_send_play_id; mpd_run_play_id; mpd_send_stop; mpd_run_stop; mpd_send_toggle_pause; mpd_run_toggle_pause; mpd_send_pause; mpd_run_pause; mpd_send_next; mpd_run_next; mpd_send_previous; mpd_run_previous; mpd_send_seek_pos; mpd_run_seek_pos; mpd_send_seek_id; mpd_run_seek_id; mpd_send_seek_id_float; mpd_run_seek_id_float; mpd_send_seek_current; mpd_run_seek_current; mpd_send_repeat; mpd_run_repeat; mpd_send_random; mpd_run_random; mpd_send_single_state; mpd_run_single_state; mpd_send_single; mpd_run_single; mpd_send_consume; mpd_run_consume; mpd_send_consume_state; mpd_run_consume_state; mpd_send_crossfade; mpd_run_crossfade; mpd_send_mixrampdb; mpd_run_mixrampdb; mpd_send_mixrampdelay; mpd_run_mixrampdelay; mpd_send_clearerror; mpd_run_clearerror; /* mpd/playlist.h */ mpd_playlist_free; mpd_playlist_dup; mpd_playlist_get_path; mpd_playlist_get_last_modified; mpd_playlist_begin; mpd_playlist_feed; mpd_send_list_playlists; mpd_recv_playlist; mpd_send_list_playlist; mpd_send_list_playlist_range; mpd_send_list_playlist_meta; mpd_send_list_playlist_range_meta; mpd_send_playlist_clear; mpd_run_playlist_clear; mpd_send_playlist_add; mpd_run_playlist_add; mpd_send_playlist_move; mpd_run_playlist_move; mpd_send_playlist_move_range; mpd_run_playlist_move_range; mpd_send_playlist_delete; mpd_run_playlist_delete; mpd_send_save; mpd_run_save; mpd_send_load; mpd_run_load; mpd_send_load_range; mpd_run_load_range; mpd_send_rename; mpd_run_rename; mpd_send_rm; mpd_run_rm; mpd_send_load_range_to; mpd_run_load_range_to; mpd_send_playlist_delete_range; mpd_run_playlist_delete_range; mpd_send_playlist_add_to; mpd_run_playlist_add_to; mpd_send_save_queue; mpd_run_save_queue; mpd_parse_queue_save_mode; mpd_lookup_queue_save_mode; mpd_send_playlistlength; mpd_playlist_search_begin; mpd_playlist_search_add_window; mpd_playlist_search_commit; mpd_playlist_search_cancel; /* mpd/queue.h */ mpd_send_list_queue_meta; mpd_send_list_queue_range_meta; mpd_send_get_queue_song_pos; mpd_run_get_queue_song_pos; mpd_send_get_queue_song_id; mpd_run_get_queue_song_id; mpd_send_queue_changes_meta; mpd_send_queue_changes_meta_range; mpd_send_queue_changes_brief; mpd_send_queue_changes_brief_range; mpd_recv_queue_change_brief; mpd_send_add; mpd_run_add; mpd_send_add_id; mpd_send_add_id_to; mpd_recv_song_id; mpd_run_add_id; mpd_run_add_id_to; mpd_send_delete; mpd_run_delete; mpd_send_delete_range; mpd_run_delete_range; mpd_send_delete_id; mpd_run_delete_id; mpd_send_shuffle; mpd_run_shuffle; mpd_send_shuffle_range; mpd_run_shuffle_range; mpd_send_clear; mpd_run_clear; mpd_send_move; mpd_run_move; mpd_send_move_id; mpd_run_move_id; mpd_send_move_range; mpd_run_move_range; mpd_send_swap; mpd_run_swap; mpd_send_swap_id; mpd_run_swap_id; mpd_send_add_tag_id; mpd_run_add_tag_id; mpd_send_clear_tag_id; mpd_run_clear_tag_id; mpd_send_clear_all_tags_id; mpd_run_clear_all_tags_id; mpd_send_prio; mpd_run_prio; mpd_send_prio_range; mpd_run_prio_range; mpd_send_prio_id; mpd_run_prio_id; mpd_send_range_id; mpd_run_range_id; mpd_send_add_id_whence; mpd_run_add_id_whence; mpd_send_add_whence; mpd_run_add_whence; mpd_send_move_whence; mpd_run_move_whence; mpd_send_move_id_whence; mpd_run_move_id_whence; mpd_send_move_range_whence; mpd_run_move_range_whence; /* mpd/recv.h */ mpd_recv_pair; mpd_recv_pair_named; mpd_return_pair; mpd_enqueue_pair; mpd_recv_binary; /* mpd/response.h */ mpd_response_finish; mpd_response_next; /* mpd/search.h */ mpd_search_db_songs; mpd_search_add_db_songs; mpd_search_add_db_songs_to_playlist; mpd_search_queue_songs; mpd_search_db_tags; mpd_count_db_songs; mpd_searchcount_db_songs; mpd_search_add_base_constraint; mpd_search_add_uri_constraint; mpd_search_add_tag_constraint; mpd_search_add_any_tag_constraint; mpd_search_add_modified_since_constraint; mpd_search_add_added_since_constraint; mpd_search_add_expression; mpd_search_add_group_tag; mpd_search_add_sort_name; mpd_search_add_sort_tag; mpd_search_add_window; mpd_search_add_position; mpd_search_commit; mpd_search_cancel; mpd_recv_pair_tag; /* mpd/send.h */ mpd_send_command; /* mpd/song.h */ mpd_song_free; mpd_song_dup; mpd_song_get_uri; mpd_song_get_tag; mpd_song_get_duration; mpd_song_get_duration_ms; mpd_song_get_start; mpd_song_get_end; mpd_song_get_last_modified; mpd_song_get_added; mpd_song_set_pos; mpd_song_get_pos; mpd_song_get_id; mpd_song_get_prio; mpd_song_get_audio_format; mpd_song_begin; mpd_song_feed; mpd_recv_song; /* mpd/stats.h */ mpd_send_stats; mpd_stats_begin; mpd_stats_feed; mpd_recv_stats; mpd_run_stats; mpd_stats_free; mpd_stats_get_number_of_artists; mpd_stats_get_number_of_albums; mpd_stats_get_number_of_songs; mpd_stats_get_uptime; mpd_stats_get_db_update_time; mpd_stats_get_play_time; mpd_stats_get_db_play_time; /* mpd/status.h */ mpd_status_begin; mpd_status_feed; mpd_status_free; mpd_send_status; mpd_recv_status; mpd_run_status; mpd_status_get_volume; mpd_status_get_repeat; mpd_status_get_random; mpd_status_get_single_state; mpd_status_get_single; mpd_status_get_consume; mpd_status_get_consume_state; mpd_status_get_queue_length; mpd_status_get_queue_version; mpd_status_get_state; mpd_status_get_crossfade; mpd_status_get_mixrampdb; mpd_status_get_mixrampdelay; mpd_status_get_song_pos; mpd_status_get_song_id; mpd_status_get_next_song_pos; mpd_status_get_next_song_id; mpd_status_get_elapsed_time; mpd_status_get_elapsed_ms; mpd_status_get_total_time; mpd_status_get_kbit_rate; mpd_status_get_audio_format; mpd_status_get_update_id; mpd_status_get_partition; mpd_status_get_error; mpd_lookup_single_state; mpd_parse_single_state; 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; mpd_tag_name_iparse; /* mpd/sticker.h */ mpd_send_sticker_set; mpd_run_sticker_set; mpd_send_sticker_delete; mpd_run_sticker_delete; mpd_send_sticker_get; mpd_send_sticker_list; mpd_send_sticker_find; mpd_parse_sticker; mpd_recv_sticker; mpd_return_sticker; mpd_send_stickernames; mpd_send_stickertypes; mpd_send_stickernamestypes; mpd_sticker_search_begin; mpd_sticker_search_add_value_constraint; mpd_sticker_search_add_sort; mpd_sticker_search_add_window; mpd_sticker_search_commit; mpd_sticker_search_cancel; mpd_send_sticker_inc; mpd_run_sticker_inc; mpd_send_sticker_dec; mpd_run_sticker_dec; /* mpd/fingerprint.h */ mpd_parse_fingerprint_type; mpd_send_getfingerprint; mpd_run_getfingerprint_chromaprint; /* mpd/partition.h */ mpd_partition_new; mpd_partition_free; mpd_partition_get_name; mpd_send_newpartition; mpd_run_newpartition; mpd_send_delete_partition; mpd_run_delete_partition; mpd_send_switch_partition; mpd_run_switch_partition; mpd_send_listpartitions; mpd_recv_partition; mpd_send_move_output; mpd_run_move_output; /* mpd/settings.h */ mpd_settings_new; mpd_settings_free; mpd_settings_get_host; mpd_settings_get_port; mpd_settings_get_timeout_ms; mpd_settings_get_password; /* mpd/replay_gain.h */ mpd_parse_replay_gain_name; mpd_lookup_replay_gain_mode; mpd_send_replay_gain_status; mpd_run_replay_gain_status; mpd_send_replay_gain_mode; mpd_run_replay_gain_mode; mpd_recv_replay_gain_status; /* mpd/binary.h */ mpd_send_binarylimit; mpd_run_binarylimit; /* mpd/albumart.h */ mpd_send_albumart; mpd_recv_albumart; mpd_run_albumart; /* mpd/readpicture.h */ mpd_send_readpicture; mpd_recv_readpicture; mpd_run_readpicture; /* mpd/position.h */ mpd_position_whence_char; local: *; }; MusicPlayerDaemon-libmpdclient-5073329/meson.build000066400000000000000000000110751505242054600221060ustar00rootroot00000000000000project('libmpdclient', 'c', version: '2.24', meson_version: '>= 0.56.0', default_options: [ 'c_std=c99', 'warning_level=3', ], license: 'BSD', ) cc = meson.get_compiler('c') project_root = meson.current_source_dir() conf = configuration_data() conf.set_quoted('PACKAGE', meson.project_name()) conf.set_quoted('VERSION', meson.project_version()) if host_machine.system() != 'windows' conf.set_quoted('DEFAULT_SOCKET', get_option('default_socket')) endif conf.set_quoted('DEFAULT_HOST', get_option('default_host')) conf.set('DEFAULT_PORT', get_option('default_port')) conf.set('HAVE_STRNDUP', cc.has_function('strndup', prefix: '#define _GNU_SOURCE\n#include ')) conf.set('HAVE_SETLOCALE', cc.has_function('setlocale', prefix: '#include ')) conf.set('HAVE_USELOCALE', cc.has_function('uselocale', prefix: '#define _GNU_SOURCE\n#include ')) platform_deps = [] if host_machine.system() == 'haiku' platform_deps = [cc.find_library('network')] endif if get_option('tcp') conf.set('ENABLE_TCP', true) conf.set('HAVE_GETADDRINFO', cc.has_function('getaddrinfo', dependencies: platform_deps)) endif configure_file(output: 'config.h', configuration: conf) splitted_version = meson.project_version().split('.') common_cflags = [ ] if cc.get_id() != 'msvc' # for strdup() with glibc common_cflags += '-D_GNU_SOURCE' endif test_cflags = [ '-Wcast-align', '-Wcast-qual', '-Wdouble-promotion', '-Wfloat-equal', '-Wmissing-declarations', '-Wmissing-noreturn', '-Wmissing-format-attribute', '-Wmissing-prototypes', '-Wno-deprecated-declarations', '-Wpointer-arith', '-Wredundant-decls', '-Wshadow', '-Wstrict-prototypes', '-Wundef', '-Wunused', '-Wwrite-strings', # clang specific warning options: '-Wunreachable-code-aggressive', ] add_project_arguments(common_cflags, language: 'c') add_project_arguments(cc.get_supported_arguments(test_cflags), language: 'c') common_ldflags = [] if host_machine.system() == 'linux' and cc.has_link_argument('-Wl,--version-script=' + join_paths(project_root, 'test.ld')) common_ldflags += '-Wl,--version-script=' + join_paths(project_root, 'libmpdclient.ld') endif if host_machine.system() == 'windows' platform_deps = [cc.find_library('ws2_32')] endif inc = include_directories( 'src', 'include', # for the generated config.h '.', ) public_inc = include_directories( 'include', ) subdir('include/mpd') libmpdclient = library('mpdclient', 'src/async.c', 'src/audio_format.c', 'src/ierror.c', 'src/resolver.c', 'src/capabilities.c', 'src/connection.c', 'src/database.c', 'src/directory.c', 'src/rdirectory.c', 'src/error.c', 'src/feature.c', 'src/fd_util.c', 'src/fingerprint.c', 'src/output.c', 'src/coutput.c', 'src/entity.c', 'src/idle.c', 'src/iso8601.c', 'src/kvlist.c', 'src/list.c', 'src/mixer.c', 'src/mount.c', 'src/cmount.c', 'src/neighbor.c', 'src/cneighbor.c', 'src/parser.c', 'src/password.c', 'src/player.c', 'src/playlist.c', 'src/player.c', 'src/rplaylist.c', 'src/cplaylist.c', 'src/queue.c', 'src/quote.c', 'src/recv.c', 'src/replay_gain.c', 'src/response.c', 'src/run.c', 'src/request.c', 'src/search.c', 'src/send.c', 'src/socket.c', 'src/song.c', 'src/status.c', 'src/cstatus.c', 'src/stats.c', 'src/cstats.c', 'src/sync.c', 'src/tag.c', 'src/sticker.c', 'src/settings.c', 'src/message.c', 'src/cmessage.c', 'src/partition.c', 'src/cpartition.c', 'src/binary.c', 'src/albumart.c', 'src/readpicture.c', 'src/position.c', 'src/stringnormalization.c', link_depends: [ 'libmpdclient.ld' ], include_directories: inc, dependencies: [ platform_deps, ], link_args: common_ldflags, version: meson.project_version(), soversion: splitted_version[0], install: true ) libmpdclient_dep = declare_dependency( link_with: libmpdclient, include_directories: public_inc, ) executable('example', 'src/example.c', dependencies: [ libmpdclient_dep, ]) docdir = join_paths(get_option('datadir'), 'doc', meson.project_name()) install_data('AUTHORS', 'LICENSES/BSD-2-Clause.txt', 'LICENSES/BSD-3-Clause.txt', 'NEWS', 'README.rst', install_dir: docdir) pkg_mod = import('pkgconfig') pkg_mod.generate( libraries: libmpdclient, version: meson.project_version(), name: 'libmpdclient', description: 'Music Player Daemon client library', ) if get_option('documentation') doxygen = find_program('doxygen', required: false) if doxygen.found() subdir('doc') endif endif if get_option('test') check_dep = dependency('check') subdir('test') endif MusicPlayerDaemon-libmpdclient-5073329/meson_options.txt000066400000000000000000000011051505242054600233720ustar00rootroot00000000000000option('default_socket', type: 'string', value: '/run/mpd/socket', description: 'The default MPD socket path') option('default_host', type: 'string', value: 'localhost', description: 'The default MPD host') option('default_port', type: 'string', value: '6600', description: 'The default MPD port') option('tcp', type: 'boolean', value: true, description: 'Enable TCP support') option('documentation', type: 'boolean', value: false, description: 'Build API documentation') option('test', type: 'boolean', value: false, description: 'Enable unit tests') MusicPlayerDaemon-libmpdclient-5073329/src/000077500000000000000000000000001505242054600205275ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/src/albumart.c000066400000000000000000000026021505242054600225020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "run.h" #include "internal.h" #include "sync.h" #include "isend.h" #include #include #include bool mpd_send_albumart(struct mpd_connection *connection, const char *uri, unsigned offset) { return mpd_send_s_u_command(connection, "albumart", uri, offset); } int mpd_recv_albumart(struct mpd_connection *connection, void *buffer, size_t buffer_size) { struct mpd_pair *pair = mpd_recv_pair_named(connection, "binary"); if (pair == NULL) { return -1; } size_t chunk_size = strtoumax(pair->value, NULL, 10); mpd_return_pair(connection, pair); size_t retrieve_bytes = chunk_size > buffer_size ? buffer_size : chunk_size; if (mpd_recv_binary(connection, buffer, retrieve_bytes) == false) { return -1; } return (int)retrieve_bytes; } int mpd_run_albumart(struct mpd_connection *connection, const char *uri, unsigned offset, void *buffer, size_t buffer_size) { if (!mpd_run_check(connection) || !mpd_send_albumart(connection, uri, offset)) { return -1; } int read_size = mpd_recv_albumart(connection, buffer, buffer_size); if (!mpd_response_finish(connection)) { return -1; } return read_size; } MusicPlayerDaemon-libmpdclient-5073329/src/async.c000066400000000000000000000164151505242054600220170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "iasync.h" #include "buffer.h" #include "ierror.h" #include "quote.h" #include "socket.h" #include #include #include #include #include #include #include #ifdef _WIN32 # include /* for SSIZE_T */ #ifndef __MINGW32__ typedef SSIZE_T ssize_t; #endif #else # include #endif #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 #endif struct mpd_async { mpd_socket_t fd; struct mpd_error_info error; struct mpd_buffer input; struct mpd_buffer output; }; struct mpd_async * mpd_async_new(int fd) { struct mpd_async *async; assert(fd != MPD_INVALID_SOCKET); async = malloc(sizeof(*async)); if (async == NULL) return NULL; async->fd = fd; mpd_error_init(&async->error); mpd_buffer_init(&async->input); mpd_buffer_init(&async->output); return async; } void mpd_async_free(struct mpd_async *async) { assert(async != NULL); mpd_socket_close(async->fd); mpd_error_deinit(&async->error); free(async); } enum mpd_error mpd_async_get_error(const struct mpd_async *async) { assert(async != NULL); return async->error.code; } const char * mpd_async_get_error_message(const struct mpd_async *async) { assert(async != NULL); return mpd_error_get_message(&async->error); } int mpd_async_get_system_error(const struct mpd_async *async) { assert(async != NULL); assert(async->error.code == MPD_ERROR_SYSTEM); return async->error.system; } bool mpd_async_copy_error(const struct mpd_async *async, struct mpd_error_info *dest) { assert(async != NULL); return mpd_error_copy(dest, &async->error); } bool mpd_async_set_error(struct mpd_async *async, enum mpd_error error, const char *error_message) { assert(async != NULL); if (mpd_error_is_defined(&async->error)) return false; mpd_error_code(&async->error, error); mpd_error_message(&async->error, error_message); return true; } int mpd_async_get_fd(const struct mpd_async *async) { assert(async != NULL); assert(async->fd != MPD_INVALID_SOCKET); return async->fd; } bool mpd_async_set_keepalive(struct mpd_async *async, bool keepalive) { assert(async != NULL); assert(async->fd != MPD_INVALID_SOCKET); return mpd_socket_keepalive(async->fd, keepalive) == 0; } enum mpd_async_event mpd_async_events(const struct mpd_async *async) { enum mpd_async_event events; assert(async != NULL); if (mpd_error_is_defined(&async->error)) return 0; /* always listen to hangups and errors */ events = MPD_ASYNC_EVENT_HUP | MPD_ASYNC_EVENT_ERROR; if (mpd_buffer_room(&async->input) > 0) /* there's room left in the input buffer: attempt to read */ events |= MPD_ASYNC_EVENT_READ; if (mpd_buffer_size(&async->output) > 0) /* there's data in the output buffer: attempt to write */ events |= MPD_ASYNC_EVENT_WRITE; return events; } static bool mpd_async_read(struct mpd_async *async) { size_t room; ssize_t nbytes; assert(async != NULL); assert(async->fd != MPD_INVALID_SOCKET); assert(!mpd_error_is_defined(&async->error)); room = mpd_buffer_room(&async->input); if (room == 0) return true; nbytes = recv(async->fd, mpd_buffer_write(&async->input), room, MSG_DONTWAIT); if (nbytes < 0) { /* I/O error */ if (mpd_socket_ignore_errno(mpd_socket_errno())) return true; mpd_error_errno(&async->error); return false; } if (nbytes == 0) { mpd_error_code(&async->error, MPD_ERROR_CLOSED); mpd_error_message(&async->error, "Connection closed by the server"); return false; } mpd_buffer_expand(&async->input, (size_t)nbytes); return true; } static bool mpd_async_write(struct mpd_async *async) { size_t size; ssize_t nbytes; assert(async != NULL); assert(async->fd != MPD_INVALID_SOCKET); assert(!mpd_error_is_defined(&async->error)); size = mpd_buffer_size(&async->output); if (size == 0) return true; nbytes = send(async->fd, mpd_buffer_read(&async->output), size, MSG_DONTWAIT); if (nbytes < 0) { /* I/O error */ if (mpd_socket_ignore_errno(mpd_socket_errno())) return true; mpd_error_errno(&async->error); return false; } mpd_buffer_consume(&async->output, (size_t)nbytes); return true; } bool mpd_async_io(struct mpd_async *async, enum mpd_async_event events) { bool success; assert(async != NULL); if (mpd_error_is_defined(&async->error)) return false; if ((events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) != 0) { mpd_error_code(&async->error, MPD_ERROR_CLOSED); mpd_error_message(&async->error, "Socket connection aborted"); return false; } if (events & MPD_ASYNC_EVENT_READ) { success = mpd_async_read(async); if (!success) return false; } assert(!mpd_error_is_defined(&async->error)); if (events & MPD_ASYNC_EVENT_WRITE) { success = mpd_async_write(async); if (!success) return false; } assert(!mpd_error_is_defined(&async->error)); return true; } bool mpd_async_send_command_v(struct mpd_async *async, const char *command, va_list args) { size_t room, length; char *dest, *end, *p; const char *arg; assert(async != NULL); assert(command != NULL); if (mpd_error_is_defined(&async->error)) return false; room = mpd_buffer_room(&async->output); length = strlen(command); if (room <= length) return false; dest = mpd_buffer_write(&async->output); /* -1 because we reserve space for the \n character */ end = dest + room - 1; /* copy the command (no quoting, we asumme it is "clean") */ memcpy(dest, command, length); p = dest + length; /* now append all arguments (quoted) */ while ((arg = va_arg(args, const char *)) != NULL) { /* append a space separator */ if (p >= end) return false; *p++ = ' '; /* quote the argument into the destination buffer */ p = quote(p, end, arg); assert(p == NULL || (p >= dest && p <= end)); if (p == NULL) return false; } /* append the newline to finish this command */ *p++ = '\n'; mpd_buffer_expand(&async->output, p - dest); return true; } bool mpd_async_send_command(struct mpd_async *async, const char *command, ...) { va_list args; bool success; assert(async != NULL); assert(command != NULL); va_start(args, command); success = mpd_async_send_command_v(async, command, args); va_end(args); return success; } char * mpd_async_recv_line(struct mpd_async *async) { size_t size; char *src, *newline; assert(async != NULL); size = mpd_buffer_size(&async->input); if (size == 0) return NULL; src = mpd_buffer_read(&async->input); assert(src != NULL); newline = memchr(src, '\n', size); if (newline == NULL) { /* line is not finished yet */ if (mpd_buffer_full(&async->input)) { /* .. but the buffer is full - line is too long, abort connection and bail out */ mpd_error_code(&async->error, MPD_ERROR_MALFORMED); mpd_error_message(&async->error, "Response line too large"); } return NULL; } *newline = 0; mpd_buffer_consume(&async->input, newline + 1 - src); return src; } size_t mpd_async_recv_raw(struct mpd_async *async, void *dest, size_t length) { size_t max_size = mpd_buffer_size(&async->input); if (max_size == 0) return 0; if (length > max_size) length = max_size; memcpy(dest, mpd_buffer_read(&async->input), length); mpd_buffer_consume(&async->input, length); return length; } MusicPlayerDaemon-libmpdclient-5073329/src/audio_format.c000066400000000000000000000024631505242054600233510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include "iaf.h" #include #include #include void mpd_parse_audio_format(struct mpd_audio_format *audio_format, const char *p) { char *endptr; if (strncmp(p, "dsd", 3) == 0) { /* allow format specifications such as "dsd64" which implies the sample rate */ unsigned long dsd = strtoul(p + 3, &endptr, 10); if (endptr > p + 3 && *endptr == ':' && dsd >= 32 && dsd <= 4096 && dsd % 2 == 0) { audio_format->sample_rate = dsd * 44100 / 8; audio_format->bits = MPD_SAMPLE_FORMAT_DSD; p = endptr + 1; audio_format->channels = (uint8_t)strtoul(p, NULL, 10); return; } } audio_format->sample_rate = strtoul(p, &endptr, 10); if (*endptr == ':') { p = endptr + 1; if (p[0] == 'f' && p[1] == ':') { audio_format->bits = MPD_SAMPLE_FORMAT_FLOAT; p += 2; } else if (p[0] == 'd' && p[1] == 's' && p[2] == 'd' && p[3] == ':') { audio_format->bits = MPD_SAMPLE_FORMAT_DSD; p += 4; } else { audio_format->bits = (uint8_t)strtoul(p, &endptr, 10); p = *endptr == ':' ? endptr + 1 : NULL; } audio_format->channels = p != NULL ? (uint8_t)strtoul(p, NULL, 10) : 0; } else { audio_format->bits = 0; audio_format->channels = 0; } } MusicPlayerDaemon-libmpdclient-5073329/src/binary.c000066400000000000000000000010311505242054600221520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include "isend.h" #include "run.h" bool mpd_send_binarylimit(struct mpd_connection *connection, unsigned limit) { return mpd_send_u_command(connection, "binarylimit", limit); } bool mpd_run_binarylimit(struct mpd_connection *connection, unsigned limit) { return mpd_run_check(connection) && mpd_send_binarylimit(connection, limit) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/buffer.h000066400000000000000000000052721505242054600221570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_BUFFER_H #define MPD_BUFFER_H #include #include #include /** * A fixed 4kB buffer which can be appended at the end, and consumed * at the beginning. */ struct mpd_buffer { /** the next buffer position to write to */ unsigned write; /** the next buffer position to read from */ unsigned read; /** the actual buffer */ unsigned char data[4096]; }; /** * Initialize an empty buffer. */ static inline void mpd_buffer_init(struct mpd_buffer *buffer) { buffer->read = 0; buffer->write = 0; } /** * Move the start of the valid data to the beginning of the allocated * buffer. */ static inline void mpd_buffer_move(struct mpd_buffer *buffer) { memmove(buffer->data, buffer->data + buffer->read, buffer->write - buffer->read); buffer->write -= buffer->read; buffer->read = 0; } /** * Determines how many bytes can be written to the buffer returned by * mpd_buffer_write(). */ static inline size_t mpd_buffer_room(const struct mpd_buffer *buffer) { assert(buffer->write <= sizeof(buffer->data)); assert(buffer->read <= buffer->write); return sizeof(buffer->data) - (buffer->write - buffer->read); } /** * Checks if the buffer is full, i.e. nothing can be written. */ static inline bool mpd_buffer_full(const struct mpd_buffer *buffer) { return mpd_buffer_room(buffer) == 0; } /** * Returns a pointer to write new data into. After you have done * that, call mpd_buffer_expand(). */ static inline void * mpd_buffer_write(struct mpd_buffer *buffer) { assert(mpd_buffer_room(buffer) > 0); mpd_buffer_move(buffer); return buffer->data + buffer->write; } /** * Moves the "write" pointer. */ static inline void mpd_buffer_expand(struct mpd_buffer *buffer, size_t nbytes) { assert(mpd_buffer_room(buffer) >= nbytes); buffer->write += (unsigned)nbytes; } /** * Determines how many bytes can be read from the pointer returned by * mpd_buffer_read(). */ static inline size_t mpd_buffer_size(const struct mpd_buffer *buffer) { assert(buffer->write <= sizeof(buffer->data)); assert(buffer->read <= buffer->write); return buffer->write - buffer->read; } /** * Returns a pointer to the head of the filled buffer. It is legal to * modify the returned buffer, for zero-copy parsing. */ static inline void * mpd_buffer_read(struct mpd_buffer *buffer) { assert(mpd_buffer_size(buffer) > 0); return buffer->data + buffer->read; } /** * Marks bytes at the beginning of the buffer as "consumed". */ static inline void mpd_buffer_consume(struct mpd_buffer *buffer, size_t nbytes) { assert(nbytes <= mpd_buffer_size(buffer)); buffer->read += (unsigned)nbytes; } #endif MusicPlayerDaemon-libmpdclient-5073329/src/capabilities.c000066400000000000000000000142711505242054600233310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include #include #include bool mpd_send_allowed_commands(struct mpd_connection *connection) { return mpd_send_command(connection, "commands", NULL); } bool mpd_send_disallowed_commands(struct mpd_connection *connection) { return mpd_send_command(connection, "notcommands", NULL); } bool mpd_send_list_url_schemes(struct mpd_connection *connection) { return mpd_send_command(connection, "urlhandlers", NULL); } bool mpd_send_list_tag_types(struct mpd_connection *connection) { return mpd_send_command(connection, "tagtypes", NULL); } bool mpd_send_list_tag_types_available(struct mpd_connection *connection) { return mpd_send_command(connection, "tagtypes", "available", NULL); } static bool mpd_send_tag_types_v(struct mpd_connection *connection, const char *sub_command, const enum mpd_tag_type *types, unsigned n) { assert(connection != NULL); assert(types != NULL); assert(n > 0); if (mpd_error_is_defined(&connection->error)) return false; char buffer[1024] = "tagtypes "; strcat(buffer, sub_command); size_t length = strlen(buffer); for (unsigned i = 0; i < n; ++i) { const char *t = mpd_tag_name(types[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, "Tag 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_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_tag_types_v(connection, "disable", types, n); } bool mpd_run_disable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_disable_tag_types(connection, types, n) && mpd_response_finish(connection); } bool mpd_send_enable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_tag_types_v(connection, "enable", types, n); } bool mpd_run_enable_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_enable_tag_types(connection, types, n) && mpd_response_finish(connection); } bool mpd_send_clear_tag_types(struct mpd_connection *connection) { return mpd_send_command(connection, "tagtypes", "clear", NULL); } bool mpd_run_clear_tag_types(struct mpd_connection *connection) { return mpd_send_clear_tag_types(connection) && mpd_response_finish(connection); } bool mpd_send_all_tag_types(struct mpd_connection *connection) { return mpd_send_command(connection, "tagtypes", "all", NULL); } bool mpd_run_all_tag_types(struct mpd_connection *connection) { return mpd_send_all_tag_types(connection) && mpd_response_finish(connection); } bool mpd_send_reset_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_tag_types_v(connection, "reset", types, n); } bool mpd_run_reset_tag_types(struct mpd_connection *connection, const enum mpd_tag_type *types, unsigned n) { return mpd_send_reset_tag_types(connection, types, n) && mpd_response_finish(connection); } bool mpd_send_list_protocol_features(struct mpd_connection *connection) { return mpd_send_command(connection, "protocol", NULL); } bool mpd_send_list_protocol_features_available(struct mpd_connection *connection) { return mpd_send_command(connection, "protocol", "available", NULL); } static bool mpd_send_protocol_features_v(struct mpd_connection *connection, const char *sub_command, const enum mpd_protocol_feature *features, unsigned n) { assert(connection != NULL); assert(features != NULL); assert(n > 0); if (mpd_error_is_defined(&connection->error)) return false; char buffer[1024] = "protocol "; strcat(buffer, sub_command); size_t length = strlen(buffer); for (unsigned i = 0; i < n; ++i) { const char *t = mpd_feature_name(features[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, "Protocol feature 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_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n) { return mpd_send_protocol_features_v(connection, "disable", features, n); } bool mpd_run_disable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n) { return mpd_send_disable_protocol_features(connection, features, n) && mpd_response_finish(connection); } bool mpd_send_enable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n) { return mpd_send_protocol_features_v(connection, "enable", features, n); } bool mpd_run_enable_protocol_features(struct mpd_connection *connection, const enum mpd_protocol_feature *features, unsigned n) { return mpd_send_enable_protocol_features(connection, features, n) && mpd_response_finish(connection); } bool mpd_send_clear_protocol_features(struct mpd_connection *connection) { return mpd_send_command(connection, "protocol", "clear", NULL); } bool mpd_run_clear_protocol_features(struct mpd_connection *connection) { return mpd_send_clear_protocol_features(connection) && mpd_response_finish(connection); } bool mpd_send_all_protocol_features(struct mpd_connection *connection) { return mpd_send_command(connection, "protocol", "all", NULL); } bool mpd_run_all_protocol_features(struct mpd_connection *connection) { return mpd_send_all_protocol_features(connection) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/cmessage.c000066400000000000000000000047751505242054600224770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include "internal.h" #include "run.h" #include #include bool mpd_send_subscribe(struct mpd_connection *connection, const char *channel) { return mpd_send_command(connection, "subscribe", channel, NULL); } bool mpd_run_subscribe(struct mpd_connection *connection, const char *channel) { return mpd_run_check(connection) && mpd_send_subscribe(connection, channel) && mpd_response_finish(connection); } bool mpd_send_unsubscribe(struct mpd_connection *connection, const char *channel) { return mpd_send_command(connection, "unsubscribe", channel, NULL); } bool mpd_run_unsubscribe(struct mpd_connection *connection, const char *channel) { return mpd_run_check(connection) && mpd_send_unsubscribe(connection, channel) && mpd_response_finish(connection); } bool mpd_send_send_message(struct mpd_connection *connection, const char *channel, const char *text) { return mpd_send_command(connection, "sendmessage", channel, text, NULL); } bool mpd_run_send_message(struct mpd_connection *connection, const char *channel, const char *text) { return mpd_run_check(connection) && mpd_send_send_message(connection, channel, text) && mpd_response_finish(connection); } bool mpd_send_read_messages(struct mpd_connection *connection) { return mpd_send_command(connection, "readmessages", NULL); } struct mpd_message * mpd_recv_message(struct mpd_connection *connection) { struct mpd_message *message; struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "channel"); if (pair == NULL) return NULL; message = mpd_message_begin(pair); mpd_return_pair(connection, pair); if (message == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_message_feed(message, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_message_free(message); return NULL; } mpd_enqueue_pair(connection, pair); if (mpd_message_get_text(message) == NULL) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "No 'message' line received"); mpd_message_free(message); return NULL; } return message; } bool mpd_send_channels(struct mpd_connection *connection) { return mpd_send_command(connection, "channels", NULL); } MusicPlayerDaemon-libmpdclient-5073329/src/cmount.c000066400000000000000000000033361505242054600222050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include "run.h" #include bool mpd_send_list_mounts(struct mpd_connection *connection) { return mpd_send_command(connection, "listmounts", NULL); } struct mpd_mount * mpd_recv_mount(struct mpd_connection *connection) { struct mpd_mount *mount; struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "mount"); if (pair == NULL) return NULL; mount = mpd_mount_begin(pair); mpd_return_pair(connection, pair); if (mount == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_mount_feed(mount, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_mount_free(mount); return NULL; } mpd_enqueue_pair(connection, pair); return mount; } bool mpd_send_mount(struct mpd_connection *connection, const char *uri, const char *storage) { return mpd_send_command(connection, "mount", uri, storage, NULL); } bool mpd_run_mount(struct mpd_connection *connection, const char *uri, const char *storage) { return mpd_run_check(connection) && mpd_send_mount(connection, uri, storage) && mpd_response_finish(connection); } bool mpd_send_unmount(struct mpd_connection *connection, const char *uri) { return mpd_send_command(connection, "unmount", uri, NULL); } bool mpd_run_unmount(struct mpd_connection *connection, const char *uri) { return mpd_run_check(connection) && mpd_send_unmount(connection, uri) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/cneighbor.c000066400000000000000000000020521505242054600226320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include bool mpd_send_list_neighbors(struct mpd_connection *connection) { return mpd_send_command(connection, "listneighbors", NULL); } struct mpd_neighbor * mpd_recv_neighbor(struct mpd_connection *connection) { struct mpd_neighbor *neighbor; struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "neighbor"); if (pair == NULL) return NULL; neighbor = mpd_neighbor_begin(pair); mpd_return_pair(connection, pair); if (neighbor == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_neighbor_feed(neighbor, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_neighbor_free(neighbor); return NULL; } mpd_enqueue_pair(connection, pair); return neighbor; } MusicPlayerDaemon-libmpdclient-5073329/src/connection.c000066400000000000000000000150011505242054600230270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "resolver.h" #include "sync.h" #include "socket.h" #include "internal.h" #include "iasync.h" #include "config.h" #include #include #include #define MPD_WELCOME_MESSAGE "OK MPD " static bool mpd_parse_welcome(struct mpd_connection *connection, const char *output) { const char *tmp; char * test; if (strncmp(output,MPD_WELCOME_MESSAGE,strlen(MPD_WELCOME_MESSAGE)) != 0) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "Malformed connect message received"); return false; } tmp = &output[strlen(MPD_WELCOME_MESSAGE)]; connection->version[0] = strtoul(tmp, &test, 10); if (test == tmp) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "Malformed version number in connect message"); return false; } if (*test == '.') { connection->version[1] = strtoul(test + 1, &test, 10); if (*test == '.') connection->version[2] = strtoul(test + 1, &test, 10); else connection->version[2] = 0; } else { connection->version[1] = 0; connection->version[2] = 0; } return true; } void mpd_connection_sync_error(struct mpd_connection *connection) { if (mpd_async_copy_error(connection->async, &connection->error)) { /* no error noticed by async: must be a timeout in the sync.c code */ mpd_error_code(&connection->error, MPD_ERROR_TIMEOUT); mpd_error_message(&connection->error, "Timeout"); } } struct mpd_connection * mpd_connection_new(const char *host, unsigned port, unsigned timeout_ms) { struct mpd_settings *initial_settings = mpd_settings_new(host, port, timeout_ms, NULL, NULL); if (initial_settings == NULL) return NULL; struct mpd_connection *connection = malloc(sizeof(*connection)); if (connection == NULL) { mpd_settings_free(initial_settings); return NULL; } const struct mpd_settings *settings; connection->initial_settings = initial_settings; connection->settings = settings = initial_settings; bool success; mpd_socket_t fd; const char *line; mpd_error_init(&connection->error); connection->async = NULL; connection->parser = NULL; connection->receiving = false; connection->sending_command_list = false; connection->pair_state = PAIR_STATE_NONE; connection->request = NULL; if (!mpd_socket_global_init(&connection->error)) return connection; mpd_connection_set_timeout(connection, mpd_settings_get_timeout_ms(settings)); fd = mpd_socket_connect(mpd_settings_get_host(settings), mpd_settings_get_port(settings), &connection->timeout, &connection->error); while (fd == MPD_INVALID_SOCKET && (settings = mpd_settings_get_next(settings)) != NULL) { connection->settings = settings; mpd_error_clear(&connection->error); fd = mpd_socket_connect(mpd_settings_get_host(settings), mpd_settings_get_port(settings), &connection->timeout, &connection->error); } if (settings == NULL) return connection; connection->async = mpd_async_new(fd); if (connection->async == NULL) { mpd_socket_close(fd); mpd_error_code(&connection->error, MPD_ERROR_OOM); return connection; } connection->parser = mpd_parser_new(); if (connection->parser == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return connection; } line = mpd_sync_recv_line(connection->async, &connection->timeout); if (line == NULL) { mpd_connection_sync_error(connection); return connection; } success = mpd_parse_welcome(connection, line); if (success) { const char *password = mpd_settings_get_password(settings); if (password != NULL) mpd_run_password(connection, password); } return connection; } struct mpd_connection * mpd_connection_new_async(struct mpd_async *async, const char *welcome) { struct mpd_connection *connection = malloc(sizeof(*connection)); assert(async != NULL); assert(welcome != NULL); if (connection == NULL) return NULL; mpd_error_init(&connection->error); connection->initial_settings = NULL; connection->settings = NULL; connection->async = async; connection->timeout.tv_sec = 30; connection->timeout.tv_usec = 0; connection->parser = NULL; connection->receiving = false; connection->sending_command_list = false; connection->pair_state = PAIR_STATE_NONE; connection->request = NULL; if (!mpd_socket_global_init(&connection->error)) return connection; connection->parser = mpd_parser_new(); if (connection->parser == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return connection; } mpd_parse_welcome(connection, welcome); return connection; } void mpd_connection_free(struct mpd_connection *connection) { assert(connection->pair_state != PAIR_STATE_FLOATING); if (connection->parser != NULL) mpd_parser_free(connection->parser); if (connection->async != NULL) mpd_async_free(connection->async); if (connection->request) free(connection->request); mpd_error_deinit(&connection->error); if (connection->initial_settings != NULL) mpd_settings_free(connection->initial_settings); free(connection); } bool mpd_connection_set_keepalive(struct mpd_connection *connection, bool keepalive) { assert(connection != NULL); return mpd_async_set_keepalive(connection->async, keepalive); } const struct mpd_settings * mpd_connection_get_settings(const struct mpd_connection *connection) { assert(connection != NULL); return connection->settings; } void mpd_connection_set_timeout(struct mpd_connection *connection, unsigned timeout_ms) { assert(timeout_ms > 0); connection->timeout.tv_sec = timeout_ms / 1000; connection->timeout.tv_usec = timeout_ms % 1000; } int mpd_connection_get_fd(const struct mpd_connection *connection) { return mpd_async_get_fd(connection->async); } struct mpd_async * mpd_connection_get_async(struct mpd_connection *connection) { return connection->async; } const unsigned * mpd_connection_get_server_version(const struct mpd_connection *connection) { return connection->version; } int mpd_connection_cmp_server_version(const struct mpd_connection *connection, unsigned major, unsigned minor, unsigned patch) { const unsigned *v = connection->version; if (v[0] > major || (v[0] == major && (v[1] > minor || (v[1] == minor && v[2] > patch)))) return 1; else if (v[0] == major && v[1] == minor && v[2] == patch) return 0; else return -1; } MusicPlayerDaemon-libmpdclient-5073329/src/coutput.c000066400000000000000000000060311505242054600223760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include "isend.h" #include "run.h" bool mpd_send_outputs(struct mpd_connection *connection) { return mpd_send_command(connection, "outputs", NULL); } struct mpd_output * mpd_recv_output(struct mpd_connection *connection) { struct mpd_output *output; struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "outputid"); if (pair == NULL) return NULL; output = mpd_output_begin(pair); mpd_return_pair(connection, pair); if (output == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_output_feed(output, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_output_free(output); return NULL; } mpd_enqueue_pair(connection, pair); return output; } bool mpd_send_enable_output(struct mpd_connection *connection, unsigned output_id) { return mpd_send_u_command(connection, "enableoutput", output_id); } bool mpd_run_enable_output(struct mpd_connection *connection, unsigned output_id) { return mpd_run_check(connection) && mpd_send_enable_output(connection, output_id) && mpd_response_finish(connection); } bool mpd_send_disable_output(struct mpd_connection *connection, unsigned output_id) { return mpd_send_u_command(connection, "disableoutput", output_id); } bool mpd_run_disable_output(struct mpd_connection *connection, unsigned output_id) { return mpd_run_check(connection) && mpd_send_disable_output(connection, output_id) && mpd_response_finish(connection); } bool mpd_send_toggle_output(struct mpd_connection *connection, unsigned output_id) { return mpd_send_u_command(connection, "toggleoutput", output_id); } bool mpd_run_toggle_output(struct mpd_connection *connection, unsigned output_id) { return mpd_run_check(connection) && mpd_send_toggle_output(connection, output_id) && mpd_response_finish(connection); } bool mpd_send_output_set(struct mpd_connection *connection, unsigned output_id, const char *attribute_name, const char *attribute_value) { return mpd_send_u_s_s_command(connection, "outputset", output_id, attribute_name, attribute_value); } bool mpd_run_output_set(struct mpd_connection *connection, unsigned output_id, const char *attribute_name, const char *attribute_value) { return mpd_run_check(connection) && mpd_send_output_set(connection, output_id, attribute_name, attribute_value) && mpd_response_finish(connection); } bool mpd_send_move_output(struct mpd_connection *connection, const char *output_name) { return mpd_send_command(connection, "moveoutput", output_name, NULL); } bool mpd_run_move_output(struct mpd_connection *connection, const char * output_name) { return mpd_run_check(connection) && mpd_send_move_output(connection, output_name) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/cpartition.c000066400000000000000000000034361505242054600230550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include "internal.h" #include "run.h" #include #include bool mpd_send_newpartition(struct mpd_connection *connection, const char *partition) { return mpd_send_command(connection, "newpartition", partition, NULL); } bool mpd_run_newpartition(struct mpd_connection *connection, const char *partition) { return mpd_run_check(connection) && mpd_send_newpartition(connection, partition) && mpd_response_finish(connection); } bool mpd_send_delete_partition(struct mpd_connection *connection, const char *partition) { return mpd_send_command(connection, "delpartition", partition, NULL); } bool mpd_run_delete_partition(struct mpd_connection *connection, const char *partition) { return mpd_run_check(connection) && mpd_send_delete_partition(connection, partition) && mpd_response_finish(connection); } bool mpd_send_switch_partition(struct mpd_connection *connection, const char *partition) { return mpd_send_command(connection, "partition", partition, NULL); } bool mpd_run_switch_partition(struct mpd_connection *connection, const char *partition) { return mpd_run_check(connection) && mpd_send_switch_partition(connection, partition) && mpd_response_finish(connection); } bool mpd_send_listpartitions(struct mpd_connection *connection) { return mpd_send_command(connection, "listpartitions", NULL); } struct mpd_partition * mpd_recv_partition(struct mpd_connection *connection) { struct mpd_pair *pair = mpd_recv_partition_pair(connection); if (pair == NULL) return NULL; struct mpd_partition *partition = mpd_partition_new(pair); mpd_return_pair(connection, pair); return partition; } MusicPlayerDaemon-libmpdclient-5073329/src/cplaylist.c000066400000000000000000000231751505242054600227070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include "internal.h" #include "isend.h" #include "request.h" #include "run.h" #include #include #include #include /* (bits+1)/3 (plus the sign character) */ enum { UNSIGNEDLEN = (sizeof(unsigned) * CHAR_BIT + 1) / 3 + 1, }; bool mpd_send_list_playlists(struct mpd_connection *connection) { return mpd_send_command(connection, "listplaylists", NULL); } bool mpd_send_list_playlist(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "listplaylist", name, NULL); } bool mpd_send_list_playlist_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_send_s_range_command(connection, "listplaylist", name, start, end); } bool mpd_send_list_playlist_meta(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "listplaylistinfo", name, NULL); } bool mpd_send_list_playlist_range_meta(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_send_s_range_command(connection, "listplaylistinfo", name, start, end); } bool mpd_send_playlist_clear(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "playlistclear", name, NULL); } bool mpd_run_playlist_clear(struct mpd_connection *connection, const char *name) { return mpd_run_check(connection) && mpd_send_playlist_clear(connection, name) && mpd_response_finish(connection); } bool mpd_send_playlist_add(struct mpd_connection *connection, const char *name, const char *path) { return mpd_send_command(connection, "playlistadd", name, path, NULL); } bool mpd_run_playlist_add(struct mpd_connection *connection, const char *name, const char *path) { return mpd_run_check(connection) && mpd_send_playlist_add(connection, name, path) && mpd_response_finish(connection); } bool mpd_send_playlist_add_to(struct mpd_connection *connection, const char *name, const char *path, unsigned to) { return mpd_send_s_s_u_command(connection, "playlistadd", name, path, to); } bool mpd_run_playlist_add_to(struct mpd_connection *connection, const char *name, const char *path, unsigned to) { return mpd_run_check(connection) && mpd_send_playlist_add_to(connection, name, path, to) && mpd_response_finish(connection); } bool mpd_send_playlist_move(struct mpd_connection *connection, const char *name, unsigned from, unsigned to) { char from_string[UNSIGNEDLEN], to_string[UNSIGNEDLEN]; snprintf(from_string, sizeof(from_string), "%u", from); snprintf(to_string, sizeof(to_string), "%u", to); return mpd_send_command(connection, "playlistmove", name, from_string, to_string, NULL); } bool mpd_run_playlist_move(struct mpd_connection *connection, const char *name, unsigned from, unsigned to) { return mpd_run_check(connection) && mpd_send_playlist_move(connection, name, from, to) && mpd_response_finish(connection); } bool mpd_send_playlist_move_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to) { return mpd_send_s_range_to_u_command(connection, "playlistmove", name, start, end, to); } bool mpd_run_playlist_move_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to) { return mpd_run_check(connection) && mpd_send_playlist_move_range(connection, name, start, end, to) && mpd_response_finish(connection); } bool mpd_send_playlist_delete(struct mpd_connection *connection, const char *name, unsigned pos) { char pos_string[UNSIGNEDLEN]; snprintf(pos_string, sizeof(pos_string), "%u", pos); return mpd_send_command(connection, "playlistdelete", name, pos_string, NULL); } bool mpd_run_playlist_delete(struct mpd_connection *connection, const char *name, unsigned pos) { return mpd_run_check(connection) && mpd_send_playlist_delete(connection, name, pos) && mpd_response_finish(connection); } bool mpd_send_playlist_delete_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_send_s_range_command(connection, "playlistdelete", name, start, end); } bool mpd_run_playlist_delete_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_run_check(connection) && mpd_send_playlist_delete_range(connection, name, start, end) && mpd_response_finish(connection); } bool mpd_send_save(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "save", name, NULL); } bool mpd_run_save(struct mpd_connection *connection, const char *name) { return mpd_run_check(connection) && mpd_send_save(connection, name) && mpd_response_finish(connection); } enum mpd_queue_save_mode mpd_parse_queue_save_mode(const char *p) { if (strcmp(p, "create") == 0) return MPD_QUEUE_SAVE_MODE_CREATE; else if (strcmp(p, "replace") == 0) return MPD_QUEUE_SAVE_MODE_REPLACE; else if (strcmp(p, "append") == 0) return MPD_QUEUE_SAVE_MODE_APPEND; else return MPD_QUEUE_SAVE_MODE_UNKNOWN; } const char * mpd_lookup_queue_save_mode(enum mpd_queue_save_mode mode) { switch (mode) { case MPD_QUEUE_SAVE_MODE_CREATE: return "create"; case MPD_QUEUE_SAVE_MODE_REPLACE: return "replace"; case MPD_QUEUE_SAVE_MODE_APPEND: return "append"; case MPD_QUEUE_SAVE_MODE_UNKNOWN: return NULL; } return NULL; } bool mpd_send_save_queue(struct mpd_connection *connection, const char *name, enum mpd_queue_save_mode mode) { const char *mode_str = mpd_lookup_queue_save_mode(mode); if (mode_str == NULL) return false; return mpd_send_command(connection, "save", name, mode_str, NULL); } bool mpd_run_save_queue(struct mpd_connection *connection, const char *name, enum mpd_queue_save_mode mode) { return mpd_run_check(connection) && mpd_send_save_queue(connection, name, mode) && mpd_response_finish(connection); } bool mpd_send_load(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "load", name, NULL); } bool mpd_run_load(struct mpd_connection *connection, const char *name) { return mpd_run_check(connection) && mpd_send_load(connection, name) && mpd_response_finish(connection); } bool mpd_send_load_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_send_s_range_command(connection, "load", name, start, end); } bool mpd_run_load_range(struct mpd_connection *connection, const char *name, unsigned start, unsigned end) { return mpd_run_check(connection) && mpd_send_load_range(connection, name, start, end) && mpd_response_finish(connection); } bool mpd_send_load_range_to(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_s_range_to_command(connection, "load", name, start, end, to_str); } bool mpd_run_load_range_to(struct mpd_connection *connection, const char *name, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence) { return mpd_run_check(connection) && mpd_send_load_range_to(connection, name, start, end, to, whence) && mpd_response_finish(connection); } bool mpd_send_rename(struct mpd_connection *connection, const char *from, const char *to) { return mpd_send_command(connection, "rename", from, to, NULL); } bool mpd_run_rename(struct mpd_connection *connection, const char *from, const char *to) { return mpd_run_check(connection) && mpd_send_rename(connection, from, to) && mpd_response_finish(connection); } bool mpd_send_rm(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "rm", name, NULL); } bool mpd_run_rm(struct mpd_connection *connection, const char *name) { return mpd_run_check(connection) && mpd_send_rm(connection, name) && mpd_response_finish(connection); } bool mpd_send_playlistlength(struct mpd_connection *connection, const char *name) { return mpd_send_command(connection, "playlistlength", name, NULL); } bool mpd_playlist_search_begin(struct mpd_connection *connection, const char *name, const char *expression) { assert(name != NULL); assert(expression != NULL); if (!mpd_request_begin(connection)) return false; char *arg_name = mpd_sanitize_arg(name); if (arg_name == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } char *arg_expression = mpd_sanitize_arg(expression); if (arg_expression == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); free(arg_name); return false; } const size_t size = 17 + strlen(arg_name) + 3 + strlen(arg_expression) + 2; connection->request = malloc(size); if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); free(arg_name); free(arg_expression); return false; } snprintf(connection->request, size, "searchplaylist \"%s\" \"%s\"", arg_name, arg_expression); free(arg_name); free(arg_expression); return true; } bool mpd_playlist_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_request_add_window(connection, start, end); } bool mpd_playlist_search_commit(struct mpd_connection *connection) { return mpd_request_commit(connection); } void mpd_playlist_search_cancel(struct mpd_connection *connection) { mpd_request_cancel(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/cstats.c000066400000000000000000000023671505242054600222040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /* * mpd_connection specific functions declared in mpd/stats.h. * */ #include #include #include #include "internal.h" #include bool mpd_send_stats(struct mpd_connection *connection) { return mpd_send_command(connection, "stats", NULL); } struct mpd_stats * mpd_recv_stats(struct mpd_connection *connection) { struct mpd_stats * stats; struct mpd_pair *pair; assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) /* refuse to receive a response if the connection's state is not clean */ return NULL; stats = mpd_stats_begin(); if (stats == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } /* read and parse all response lines */ while ((pair = mpd_recv_pair(connection)) != NULL) { mpd_stats_feed(stats, pair); mpd_return_pair(connection, pair); } if (mpd_error_is_defined(&connection->error)) { /* an error has occurred; roll back */ mpd_stats_free(stats); return NULL; } return stats; } struct mpd_stats * mpd_run_stats(struct mpd_connection *connection) { return mpd_send_stats(connection) ? mpd_recv_stats(connection) : NULL; } MusicPlayerDaemon-libmpdclient-5073329/src/cstatus.c000066400000000000000000000021441505242054600223620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /* * mpd_connection specific functions declared in mpd/status.h. * */ #include #include #include #include "internal.h" #include "run.h" bool mpd_send_status(struct mpd_connection * connection) { return mpd_send_command(connection, "status", NULL); } struct mpd_status * mpd_recv_status(struct mpd_connection * connection) { struct mpd_status * status; struct mpd_pair *pair; if (mpd_error_is_defined(&connection->error)) return NULL; status = mpd_status_begin(); if (status == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL) { mpd_status_feed(status, pair); mpd_return_pair(connection, pair); } if (mpd_error_is_defined(&connection->error)) { mpd_status_free(status); return NULL; } return status; } struct mpd_status * mpd_run_status(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_status(connection) ? mpd_recv_status(connection) : NULL; } MusicPlayerDaemon-libmpdclient-5073329/src/database.c000066400000000000000000000041011505242054600224330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include "run.h" #include #include bool mpd_send_list_all(struct mpd_connection *connection, const char *dir) { return mpd_send_command(connection, "listall", dir, NULL); } bool mpd_send_list_all_meta(struct mpd_connection *connection, const char *dir) { return mpd_send_command(connection, "listallinfo", dir, NULL); } bool mpd_send_list_meta(struct mpd_connection *connection, const char *dir) { return mpd_send_command(connection, "lsinfo", dir, NULL); } bool mpd_send_list_files(struct mpd_connection *connection, const char *uri) { return mpd_send_command(connection, "listfiles", uri, NULL); } bool mpd_send_read_comments(struct mpd_connection *connection, const char *path) { return mpd_send_command(connection, "readcomments", path, NULL); } bool mpd_send_update(struct mpd_connection *connection, const char *path) { return mpd_send_command(connection, "update", path, NULL); } bool mpd_send_rescan(struct mpd_connection *connection, const char *path) { return mpd_send_command(connection, "rescan", path, NULL); } unsigned mpd_recv_update_id(struct mpd_connection *connection) { struct mpd_pair *pair; unsigned ret = 0; pair = mpd_recv_pair_named(connection, "updating_db"); if (pair != NULL) { ret = strtoul(pair->value, NULL, 10); mpd_return_pair(connection, pair); } return ret; } unsigned mpd_run_update(struct mpd_connection *connection, const char *path) { unsigned id; if (!mpd_run_check(connection) || !mpd_send_update(connection, path)) return 0; id = mpd_recv_update_id(connection); return id != 0 && mpd_response_finish(connection) ? id : 0; } unsigned mpd_run_rescan(struct mpd_connection *connection, const char *path) { unsigned id; if (!mpd_run_check(connection) || !mpd_send_rescan(connection, path)) return 0; id = mpd_recv_update_id(connection); return id != 0 && mpd_response_finish(connection) ? id : 0; } MusicPlayerDaemon-libmpdclient-5073329/src/directory.c000066400000000000000000000045461505242054600227100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include "uri.h" #include "iso8601.h" #include #include #include #include struct mpd_directory { /** * The full path of this directory. It does not begin with a * slash. */ char *path; /** * The POSIX UTC time stamp of the last modification, or 0 if * that is unknown. */ time_t last_modified; }; mpd_malloc static struct mpd_directory * mpd_directory_new(const char *path) { struct mpd_directory *directory; assert(path != NULL); assert(mpd_verify_local_uri(path)); directory = malloc(sizeof(*directory)); if (directory == NULL) /* out of memory */ return NULL; directory->path = strdup(path); if (directory->path == NULL) { /* out of memory */ free(directory); return NULL; } directory->last_modified = 0; return directory; } void mpd_directory_free(struct mpd_directory *directory) { assert(directory != NULL); assert(directory->path != NULL); free(directory->path); free(directory); } struct mpd_directory * mpd_directory_dup(const struct mpd_directory *directory) { assert(directory != NULL); assert(directory->path != NULL); struct mpd_directory *copy = mpd_directory_new(directory->path); copy->last_modified = directory->last_modified; return copy; } const char * mpd_directory_get_path(const struct mpd_directory *directory) { assert(directory != NULL); assert(directory->path != NULL); return directory->path; } time_t mpd_directory_get_last_modified(const struct mpd_directory *directory) { assert(directory != NULL); return directory->last_modified; } struct mpd_directory * mpd_directory_begin(const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "directory") != 0 || !mpd_verify_local_uri(pair->value)) { errno = EINVAL; return NULL; } return mpd_directory_new(pair->value); } bool mpd_directory_feed(struct mpd_directory *directory, const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "directory") == 0) return false; if (strcmp(pair->name, "Last-Modified") == 0) directory->last_modified = iso8601_datetime_parse(pair->value); return true; } MusicPlayerDaemon-libmpdclient-5073329/src/entity.c000066400000000000000000000104151505242054600222100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include "internal.h" #include #include #include struct mpd_entity { /** * The type of this entity. */ enum mpd_entity_type type; /** * This union contains type-safe pointers to the real object. * Check the entity type before attempting to obtain the * object! */ union { /** * Only valid if type==#MPD_ENTITY_TYPE_DIRECTORY. */ struct mpd_directory *directory; /** * Only valid if type==#MPD_ENTITY_TYPE_SONG. */ struct mpd_song *song; /** * Only valid if type==#MPD_ENTITY_TYPE_PLAYLIST. */ struct mpd_playlist *playlistFile; } info; }; void mpd_entity_free(struct mpd_entity *entity) { assert(entity != NULL); switch (entity->type) { case MPD_ENTITY_TYPE_UNKNOWN: /* nothing to free */ break; case MPD_ENTITY_TYPE_DIRECTORY: mpd_directory_free(entity->info.directory); break; case MPD_ENTITY_TYPE_SONG: mpd_song_free(entity->info.song); break; case MPD_ENTITY_TYPE_PLAYLIST: mpd_playlist_free(entity->info.playlistFile); break; } free(entity); } enum mpd_entity_type mpd_entity_get_type(const struct mpd_entity *entity) { assert(entity != NULL); return entity->type; } const struct mpd_directory * mpd_entity_get_directory(const struct mpd_entity *entity) { assert(entity != NULL); assert(entity->type == MPD_ENTITY_TYPE_DIRECTORY); return entity->info.directory; } const struct mpd_song * mpd_entity_get_song(const struct mpd_entity *entity) { assert(entity != NULL); assert(entity->type == MPD_ENTITY_TYPE_SONG); return entity->info.song; } const struct mpd_playlist * mpd_entity_get_playlist(const struct mpd_entity *entity) { assert(entity != NULL); assert(entity->type == MPD_ENTITY_TYPE_PLAYLIST); return entity->info.playlistFile; } static bool mpd_entity_feed_first(struct mpd_entity *entity, const struct mpd_pair *pair) { if (strcmp(pair->name, "file") == 0) { entity->type = MPD_ENTITY_TYPE_SONG; entity->info.song = mpd_song_begin(pair); if (entity->info.song == NULL) return false; } else if (strcmp(pair->name, "directory") == 0) { entity->type = MPD_ENTITY_TYPE_DIRECTORY; entity->info.directory = mpd_directory_begin(pair); if (entity->info.directory == NULL) return false; } else if (strcmp(pair->name, "playlist") == 0) { entity->type = MPD_ENTITY_TYPE_PLAYLIST; entity->info.playlistFile = mpd_playlist_begin(pair); if (entity->info.playlistFile == NULL) return false; } else { entity->type = MPD_ENTITY_TYPE_UNKNOWN; } return true; } struct mpd_entity * mpd_entity_begin(const struct mpd_pair *pair) { struct mpd_entity *entity; bool success; entity = malloc(sizeof(*entity)); if (entity == NULL) /* out of memory */ return NULL; success = mpd_entity_feed_first(entity, pair); if (!success) { free(entity); return NULL; } return entity; } bool mpd_entity_feed(struct mpd_entity *entity, const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "file") == 0 || strcmp(pair->name, "directory") == 0 || strcmp(pair->name, "playlist") == 0) return false; switch (entity->type) { case MPD_ENTITY_TYPE_UNKNOWN: break; case MPD_ENTITY_TYPE_DIRECTORY: mpd_directory_feed(entity->info.directory, pair); break; case MPD_ENTITY_TYPE_SONG: mpd_song_feed(entity->info.song, pair); break; case MPD_ENTITY_TYPE_PLAYLIST: mpd_playlist_feed(entity->info.playlistFile, pair); break; } return true; } struct mpd_entity * mpd_recv_entity(struct mpd_connection *connection) { struct mpd_pair *pair; struct mpd_entity *entity; pair = mpd_recv_pair(connection); if (pair == NULL) return NULL; entity = mpd_entity_begin(pair); mpd_return_pair(connection, pair); if (entity == NULL) { mpd_error_entity(&connection->error); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_entity_feed(entity, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { mpd_entity_free(entity); return NULL; } /* unread this pair for the next mpd_recv_entity() call */ mpd_enqueue_pair(connection, pair); return entity; } MusicPlayerDaemon-libmpdclient-5073329/src/error.c000066400000000000000000000022251505242054600220250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include "internal.h" #include enum mpd_error mpd_connection_get_error(const struct mpd_connection *connection) { return connection->error.code; } const char * mpd_connection_get_error_message(const struct mpd_connection *connection) { return mpd_error_get_message(&connection->error); } enum mpd_server_error mpd_connection_get_server_error(const struct mpd_connection *connection) { assert(connection->error.code == MPD_ERROR_SERVER); return connection->error.server; } unsigned mpd_connection_get_server_error_location(const struct mpd_connection *connection) { assert(connection->error.code == MPD_ERROR_SERVER); return connection->error.at; } int mpd_connection_get_system_error(const struct mpd_connection *connection) { assert(connection->error.code == MPD_ERROR_SYSTEM); return connection->error.system; } bool mpd_connection_clear_error(struct mpd_connection *connection) { if (mpd_error_is_fatal(&connection->error)) /* impossible to recover */ return false; mpd_error_clear(&connection->error); return true; } MusicPlayerDaemon-libmpdclient-5073329/src/example.c000066400000000000000000000272331505242054600223350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include #include #include #include static int handle_error(struct mpd_connection *c) { assert(mpd_connection_get_error(c) != MPD_ERROR_SUCCESS); fprintf(stderr, "%s\n", mpd_connection_get_error_message(c)); mpd_connection_free(c); return EXIT_FAILURE; } static void print_tag(const struct mpd_song *song, enum mpd_tag_type type, const char *label) { unsigned i = 0; const char *value; while ((value = mpd_song_get_tag(song, type, i++)) != NULL) printf("%s: %s\n", label, value); } static int readpicture(struct mpd_connection *c, const char *uri) { unsigned long long offset = 0; unsigned long long total_size; do { char offset_s[32]; snprintf(offset_s, sizeof(offset_s), "%lu", (unsigned long)offset); if (!mpd_send_command(c, "readpicture", uri, offset_s, NULL)) return handle_error(c); struct mpd_pair *pair = mpd_recv_pair_named(c, "size"); if (pair == NULL) { if (mpd_connection_get_error(c) != MPD_ERROR_SUCCESS) return handle_error(c); fprintf(stderr, "No 'size'\n"); return EXIT_FAILURE; } total_size = strtoull(pair->value, NULL, 10); mpd_return_pair(c, pair); pair = mpd_recv_pair_named(c, "binary"); if (pair == NULL) { if (mpd_connection_get_error(c) != MPD_ERROR_SUCCESS) return handle_error(c); fprintf(stderr, "No 'binary'\n"); return EXIT_FAILURE; } const unsigned long long chunk_size = strtoull(pair->value, NULL, 10); mpd_return_pair(c, pair); if (chunk_size == 0) break; char *p = malloc(chunk_size); if (p == NULL) abort(); if (!mpd_recv_binary(c, p, chunk_size)) return handle_error(c); if (!mpd_response_finish(c)) return handle_error(c); if (fwrite(p, chunk_size, 1, stdout) != 1) exit(EXIT_FAILURE); free(p); offset += chunk_size; } while (offset < total_size); return EXIT_SUCCESS; } int main(int argc, char ** argv) { struct mpd_connection *conn; conn = mpd_connection_new(NULL, 0, 30000); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); if(argc==1) { for(int i=0;i<3;i++) { printf("version[%i]: %i\n",i, mpd_connection_get_server_version(conn)[i]); } struct mpd_status * status; struct mpd_song *song; const struct mpd_audio_format *audio_format; mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); status = mpd_recv_status(conn); if (status == NULL) return handle_error(conn); printf("volume: %i\n", mpd_status_get_volume(status)); printf("repeat: %i\n", mpd_status_get_repeat(status)); printf("queue version: %u\n", mpd_status_get_queue_version(status)); printf("queue length: %i\n", mpd_status_get_queue_length(status)); if (mpd_status_get_error(status) != NULL) printf("error: %s\n", mpd_status_get_error(status)); if (mpd_status_get_state(status) == MPD_STATE_PLAY || mpd_status_get_state(status) == MPD_STATE_PAUSE) { printf("song: %i\n", mpd_status_get_song_pos(status)); printf("elaspedTime: %i\n",mpd_status_get_elapsed_time(status)); printf("elasped_ms: %u\n", mpd_status_get_elapsed_ms(status)); printf("totalTime: %i\n", mpd_status_get_total_time(status)); printf("bitRate: %i\n", mpd_status_get_kbit_rate(status)); } audio_format = mpd_status_get_audio_format(status); if (audio_format != NULL) { printf("sampleRate: %i\n", audio_format->sample_rate); printf("bits: %i\n", audio_format->bits); printf("channels: %i\n", audio_format->channels); } mpd_status_free(status); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); mpd_response_next(conn); while ((song = mpd_recv_song(conn)) != NULL) { printf("uri: %s\n", mpd_song_get_uri(song)); print_tag(song, MPD_TAG_ARTIST, "artist"); print_tag(song, MPD_TAG_ALBUM, "album"); print_tag(song, MPD_TAG_TITLE, "title"); print_tag(song, MPD_TAG_TRACK, "track"); print_tag(song, MPD_TAG_NAME, "name"); print_tag(song, MPD_TAG_DATE, "date"); if (mpd_song_get_duration(song) > 0) { printf("time: %u\n", mpd_song_get_duration(song)); } printf("pos: %u\n", mpd_song_get_pos(song)); mpd_song_free(song); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if(argc==3 && strcmp(argv[1],"lsinfo")==0) { struct mpd_entity * entity; if (!mpd_send_list_meta(conn, argv[2])) return handle_error(conn); while ((entity = mpd_recv_entity(conn)) != NULL) { const struct mpd_song *song; const struct mpd_directory *dir; const struct mpd_playlist *pl; switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_UNKNOWN: break; case MPD_ENTITY_TYPE_SONG: song = mpd_entity_get_song(entity); printf("uri: %s\n", mpd_song_get_uri(song)); print_tag(song, MPD_TAG_ARTIST, "artist"); print_tag(song, MPD_TAG_ALBUM, "album"); print_tag(song, MPD_TAG_TITLE, "title"); print_tag(song, MPD_TAG_TRACK, "track"); break; case MPD_ENTITY_TYPE_DIRECTORY: dir = mpd_entity_get_directory(entity); printf("directory: %s\n", mpd_directory_get_path(dir)); break; case MPD_ENTITY_TYPE_PLAYLIST: pl = mpd_entity_get_playlist(entity); printf("playlist: %s\n", mpd_playlist_get_path(pl)); break; } mpd_entity_free(entity); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 3 && strcmp(argv[1], "readpicture") == 0) { int result = readpicture(conn, argv[2]); if (result != EXIT_SUCCESS) return result; } else if(argc==2 && strcmp(argv[1],"artists")==0) { struct mpd_pair *pair; if (!mpd_search_db_tags(conn, MPD_TAG_ARTIST) || !mpd_search_commit(conn)) return handle_error(conn); while ((pair = mpd_recv_pair_tag(conn, MPD_TAG_ARTIST)) != NULL) { printf("%s\n", pair->value); mpd_return_pair(conn, pair); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "playlists") == 0) { if (!mpd_send_list_playlists(conn)) return handle_error(conn); struct mpd_playlist *playlist; while ((playlist = mpd_recv_playlist(conn)) != NULL) { printf("%s\n", mpd_playlist_get_path(playlist)); mpd_playlist_free(playlist); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "idle") == 0) { enum mpd_idle idle = mpd_run_idle(conn); if (idle == 0 && mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); for (unsigned j = 0;; ++j) { enum mpd_idle i = 1 << j; const char *name = mpd_idle_name(i); if (name == NULL) break; if (idle & i) printf("%s\n", name); } } else if (argc == 3 && strcmp(argv[1], "subscribe") == 0) { /* subscribe to a channel and print all messages */ if (!mpd_run_subscribe(conn, argv[2])) return handle_error(conn); while (mpd_run_idle_mask(conn, MPD_IDLE_MESSAGE) != 0) { if (!mpd_send_read_messages(conn)) return handle_error(conn); struct mpd_message *msg; while ((msg = mpd_recv_message(conn)) != NULL) { printf("%s\n", mpd_message_get_text(msg)); mpd_message_free(msg); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "channels") == 0) { /* print a list of channels */ if (!mpd_send_channels(conn)) return handle_error(conn); struct mpd_pair *pair; while ((pair = mpd_recv_channel_pair(conn)) != NULL) { printf("%s\n", pair->value); mpd_return_pair(conn, pair); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 4 && strcmp(argv[1], "message") == 0) { /* send a message to a channel */ if (!mpd_run_send_message(conn, argv[2], argv[3])) return handle_error(conn); } else if (argc == 3 && strcmp(argv[1], "fingerprint") == 0) { char buffer[8192]; const char *fingerprint = mpd_run_getfingerprint_chromaprint(conn, argv[2], buffer, sizeof(buffer)); if (fingerprint == NULL) return handle_error(conn); printf("%s\n", fingerprint); } else if (argc == 2 && strcmp(argv[1], "listneighbors") == 0) { struct mpd_neighbor *neighbor; if (!mpd_send_list_neighbors(conn)) return handle_error(conn); while ((neighbor = mpd_recv_neighbor(conn)) != NULL) { printf("uri: %s\n display name: %s\n", mpd_neighbor_get_uri(neighbor), mpd_neighbor_get_display_name(neighbor)); mpd_neighbor_free(neighbor); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 3 && strcmp(argv[1], "newpartition") == 0) { if (!mpd_run_newpartition(conn, argv[2])) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "listpartitions") == 0) { struct mpd_pair *pair; struct mpd_partition *part; if (!mpd_send_listpartitions(conn)) return handle_error(conn); while ((pair = mpd_recv_partition_pair(conn)) != NULL) { part = mpd_partition_new(pair); if (part == NULL) return handle_error(conn); mpd_return_pair(conn, pair); printf("partition name: %s\n", mpd_partition_get_name(part)); mpd_partition_free(part); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "idle_partition") == 0) { while (mpd_run_idle_mask(conn, MPD_IDLE_PARTITION) != 0) { struct mpd_pair *pair; struct mpd_partition *part; if (!mpd_send_listpartitions(conn)) return handle_error(conn); while ((pair = mpd_recv_partition_pair(conn)) != NULL) { part = mpd_partition_new(pair); if (part == NULL) return handle_error(conn); mpd_return_pair(conn, pair); printf("partition name: %s\n", mpd_partition_get_name(part)); mpd_partition_free(part); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) handle_error(conn); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) handle_error(conn); } else if (argc == 3 && strcmp(argv[1], "switchpartition") == 0) { if (!mpd_run_switch_partition(conn, argv[2])) return handle_error(conn); printf("switched to partition %s\n", argv[2]); } else if (argc == 2 && strcmp(argv[1], "replay_gain_status") == 0) { const enum mpd_replay_gain_mode mode = mpd_run_replay_gain_status(conn); if (mode == MPD_REPLAY_UNKNOWN) return handle_error(conn); printf("replay gain status: %d\n", mode); } else if (argc == 3 && strcmp(argv[1], "replay_gain_mode") == 0) { const enum mpd_replay_gain_mode mode = mpd_parse_replay_gain_name(argv[2]); if (mode == MPD_REPLAY_UNKNOWN) { printf("Unknown replay mode %s\n", argv[2]); return EXIT_FAILURE; } if (!mpd_run_replay_gain_mode(conn, mode)) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "getvol") == 0) { int volume = mpd_run_get_volume(conn); if (volume == -1) return handle_error(conn); printf("Volume: %d\n", volume); } else if (argc == 3 && strcmp(argv[1], "binarylimit") == 0) { unsigned limit = (unsigned)strtoul(argv[2], NULL, 10); if (!mpd_run_binarylimit(conn, limit)) return handle_error(conn); } mpd_connection_free(conn); return 0; } MusicPlayerDaemon-libmpdclient-5073329/src/fd_util.c000066400000000000000000000032641505242054600223260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /* * This code is copied from MPD. It is a subset of the original * library (we don't need pipes and regular files in libmpdclient). * */ #include "fd_util.h" #include #include #include #include #ifdef _WIN32 #include #else #include #endif #ifndef _WIN32 static int fd_mask_flags(mpd_socket_t fd, int and_mask, int xor_mask) { int ret; assert(fd != MPD_INVALID_SOCKET); ret = fcntl(fd, F_GETFD, 0); if (ret < 0) return ret; return fcntl(fd, F_SETFD, (ret & and_mask) ^ xor_mask); } #endif /* !_WIN32 */ static int fd_set_cloexec(mpd_socket_t fd, bool enable) { #ifndef _WIN32 return fd_mask_flags(fd, ~FD_CLOEXEC, enable ? FD_CLOEXEC : 0); #else (void)fd; (void)enable; return 0; #endif } /** * Enables non-blocking mode for the specified file descriptor. On * WIN32, this function only works for sockets. */ static int fd_set_nonblock(mpd_socket_t fd) { #ifdef _WIN32 u_long val = 1; return ioctlsocket(fd, FIONBIO, &val); #else int flags; assert(fd != MPD_INVALID_SOCKET); flags = fcntl(fd, F_GETFL); if (flags < 0) return flags; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); #endif } mpd_socket_t socket_cloexec_nonblock(int domain, int type, int protocol) { mpd_socket_t fd; #if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) fd = socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol); if (fd != MPD_INVALID_SOCKET || errno != EINVAL) return fd; #endif fd = socket(domain, type, protocol); if (fd != MPD_INVALID_SOCKET) { fd_set_cloexec(fd, true); fd_set_nonblock(fd); } return fd; } MusicPlayerDaemon-libmpdclient-5073329/src/fd_util.h000066400000000000000000000010251505242054600223240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /* * This library provides easy helper functions for working with file * descriptors. It has wrappers for taking advantage of Linux 2.6 * specific features like O_CLOEXEC. * */ #ifndef FD_UTIL_H #define FD_UTIL_H #include /** * Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag * (atomically if supported by the OS). */ mpd_socket_t socket_cloexec_nonblock(int domain, int type, int protocol); #endif MusicPlayerDaemon-libmpdclient-5073329/src/feature.c000066400000000000000000000013441505242054600223300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include static const char *const mpd_feature_names[MPD_FEATURE_COUNT] = { [MPD_FEATURE_HIDE_PLAYLISTS_IN_ROOT] = "hide_playlists_in_root", }; const char * mpd_feature_name(enum mpd_protocol_feature feature) { if ((unsigned)feature >= MPD_FEATURE_COUNT) return NULL; return mpd_feature_names[feature]; } enum mpd_protocol_feature mpd_feature_name_parse(const char *name) { assert(name != NULL); for (unsigned i = 0; i < MPD_FEATURE_COUNT; ++i) if (strcmp(name, mpd_feature_names[i]) == 0) return (enum mpd_protocol_feature)i; return MPD_FEATURE_UNKNOWN; } MusicPlayerDaemon-libmpdclient-5073329/src/fingerprint.c000066400000000000000000000022351505242054600232240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include "run.h" #include #include bool mpd_send_getfingerprint(struct mpd_connection *connection, const char *uri) { return mpd_send_command(connection, "getfingerprint", uri, NULL); } enum mpd_fingerprint_type mpd_parse_fingerprint_type(const char *name) { if (strcmp(name, "chromaprint") == 0) return MPD_FINGERPRINT_TYPE_CHROMAPRINT; else return MPD_FINGERPRINT_TYPE_UNKNOWN; } const char * mpd_run_getfingerprint_chromaprint(struct mpd_connection *connection, const char *uri, char *buffer, size_t buffer_size) { if (!mpd_run_check(connection) || !mpd_send_getfingerprint(connection, uri)) return NULL; const char *result = NULL; struct mpd_pair *pair = mpd_recv_pair_named(connection, "chromaprint"); if (pair != NULL) { snprintf(buffer, buffer_size, "%s", pair->value); result = buffer; mpd_return_pair(connection, pair); } if (!mpd_response_finish(connection)) result = NULL; return result; } MusicPlayerDaemon-libmpdclient-5073329/src/iaf.h000066400000000000000000000010511505242054600214340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_INTERNAL_AUDIO_FORMAT_H #define MPD_INTERNAL_AUDIO_FORMAT_H #include #include struct mpd_audio_format; void mpd_parse_audio_format(struct mpd_audio_format *audio_format, const char *p); static inline bool mpd_audio_format_is_empty(const struct mpd_audio_format *audio_format) { return audio_format->sample_rate == 0 && audio_format->bits == MPD_SAMPLE_FORMAT_UNDEFINED && audio_format->channels == 0; } #endif MusicPlayerDaemon-libmpdclient-5073329/src/iasync.h000066400000000000000000000014551505242054600221730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #ifndef MPD_IASYNC_H #define MPD_IASYNC_H #include struct mpd_error_info; /** * Creates a copy of that object's error condition. * * @return true if there was no error in #async, false if an error * condition is stored in #async (in both cases, the information is * copied) */ bool mpd_async_copy_error(const struct mpd_async *async, struct mpd_error_info *dest); /** * Sets the object's error condition. * * @return true if there was no error in #async, false if an error * condition is stored in #async; the #error is only set if there was no error * previously present */ bool mpd_async_set_error(struct mpd_async *async, enum mpd_error error, const char *error_message); #endif MusicPlayerDaemon-libmpdclient-5073329/src/idle.c000066400000000000000000000101731505242054600216120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "internal.h" #include "isend.h" #include "run.h" #include static const char *const idle_names[] = { "database", "stored_playlist", "playlist", "player", "mixer", "output", "options", "update", "sticker", "subscription", "message", "partition", "neighbor", "mount", NULL }; const char * mpd_idle_name(enum mpd_idle idle) { for (unsigned i = 0; idle_names[i] != NULL; ++i) if (idle == (enum mpd_idle)(1 << i)) return idle_names[i]; return NULL; } enum mpd_idle mpd_idle_name_parse(const char *name) { assert(name != NULL); for (unsigned i = 0; idle_names[i] != NULL; ++i) if (strcmp(name, idle_names[i]) == 0) return 1 << i; return 0; } enum mpd_idle mpd_idle_parse_pair(const struct mpd_pair *pair) { assert(pair != NULL); if (strcmp(pair->name, "changed") != 0) return 0; return mpd_idle_name_parse(pair->value); } enum mpd_idle mpd_recv_idle(struct mpd_connection *connection, bool disable_timeout) { enum mpd_idle flags = 0; struct mpd_pair *pair; struct timeval old_timeout; assert(connection != NULL); /* temporarily disable the connection timeout */ if (disable_timeout) { /* make sure that the output buffer is empty before we turn off the timeout - this is important because we want to detect a send failure more quickly */ if (!mpd_flush(connection)) return 0; old_timeout = connection->timeout; connection->timeout = (struct timeval){ .tv_sec = 0, .tv_usec = 0, }; } else { /* work around bogus gcc warning "may be used uninitialized"; gcc is too dumb to see that we're accessing old_timeout only if it was initialized */ old_timeout = (struct timeval){ .tv_sec = 0, .tv_usec = 0, }; } while ((pair = mpd_recv_pair(connection)) != NULL) { flags |= mpd_idle_parse_pair(pair); mpd_return_pair(connection, pair); } /* re-enable timeout */ if (disable_timeout) connection->timeout = old_timeout; return flags; } bool mpd_send_idle(struct mpd_connection *connection) { return mpd_send_command(connection, "idle", NULL); } bool mpd_send_idle_mask(struct mpd_connection *connection, enum mpd_idle mask) { /* this buffer is large enough even for the full mask */ char buffer[128] = "idle"; assert(mask != 0); if (mpd_error_is_defined(&connection->error)) return false; for (unsigned i = 0; idle_names[i] != NULL; ++i) { if (mask & (1 << i)) { mask &= ~(1 << i); strcat(buffer, " "); strcat(buffer, idle_names[i]); } } if (mask != 0) { /* the client expects that all flags are supported, because he might block forever if an event is not delivered as expected */ mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); mpd_error_printf(&connection->error, "Unsupported idle flags: 0x%x", mask); return false; } return mpd_send_command(connection, buffer, NULL); } bool mpd_send_noidle(struct mpd_connection *connection) { /* we need this workaround, because "noidle" may be sent while the "idle" response is being received */ connection->receiving = false; return mpd_send_command(connection, "noidle", NULL); } enum mpd_idle mpd_run_idle(struct mpd_connection *connection) { enum mpd_idle flags; if (!mpd_run_check(connection) || !mpd_send_idle(connection)) return 0; flags = mpd_recv_idle(connection, true); if (!mpd_response_finish(connection)) return 0; return flags; } enum mpd_idle mpd_run_idle_mask(struct mpd_connection *connection, enum mpd_idle mask) { enum mpd_idle flags; if (!mpd_run_check(connection) || !mpd_send_idle_mask(connection, mask)) return 0; flags = mpd_recv_idle(connection, true); if (!mpd_response_finish(connection)) return 0; return flags; } enum mpd_idle mpd_run_noidle(struct mpd_connection *connection) { enum mpd_idle flags; if (!mpd_run_check(connection) || !mpd_send_noidle(connection)) return 0; flags = mpd_recv_idle(connection, false); if (!mpd_response_finish(connection)) return 0; return flags; } MusicPlayerDaemon-libmpdclient-5073329/src/ierror.c000066400000000000000000000051761505242054600222060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "ierror.h" #include "socket.h" #include #include #include #include #include void mpd_error_deinit(struct mpd_error_info *error) { assert(error != NULL); if (error->code != MPD_ERROR_SUCCESS) free(error->message); } void mpd_error_message(struct mpd_error_info *error, const char *message) { assert(error != NULL); assert(message != NULL); assert(mpd_error_is_defined(error)); assert(error->message == NULL); error->message = strdup(message); if (error->message == NULL) error->code = MPD_ERROR_OOM; } void mpd_error_message_n(struct mpd_error_info *error, const char *message, size_t length) { assert(error != NULL); assert(message != NULL); assert(mpd_error_is_defined(error)); assert(error->message == NULL); error->message = malloc(length + 1); if (error->message != NULL) { memcpy(error->message, message, length); error->message[length] = 0; } else error->code = MPD_ERROR_OOM; } void mpd_error_printf(struct mpd_error_info *error, const char *fmt, ...) { char buffer[1024]; va_list ap; assert(error != NULL); assert(fmt != NULL); va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); mpd_error_message(error, buffer); } void mpd_error_system_message(struct mpd_error_info *error, int code) { #ifdef _WIN32 char buffer[1024]; DWORD nbytes; #endif assert(error != NULL); mpd_error_system(error, code); #ifdef _WIN32 nbytes = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, code, 0, (LPSTR)buffer, sizeof(buffer), NULL); mpd_error_message(error, nbytes > 0 ? buffer : "Unknown error"); #else mpd_error_message(error, strerror(code)); #endif } void mpd_error_errno(struct mpd_error_info *error) { assert(error != NULL); mpd_error_system_message(error, mpd_socket_errno()); } void mpd_error_entity(struct mpd_error_info *error) { if (errno == EINVAL) { mpd_error_code(error, MPD_ERROR_MALFORMED); mpd_error_message(error, "Malformed entity response line"); } else mpd_error_code(error, MPD_ERROR_OOM); } bool mpd_error_copy(struct mpd_error_info *dest, const struct mpd_error_info *src) { assert(dest != NULL); assert(src != NULL); dest->code = src->code; if (src->code == MPD_ERROR_SUCCESS) return true; if (src->code == MPD_ERROR_SERVER) { dest->server = src->server; dest->at = src->at; } else if (src->code == MPD_ERROR_SYSTEM) dest->system = src->system; dest->message = src->message != NULL ? strdup(src->message) : NULL; return false; } MusicPlayerDaemon-libmpdclient-5073329/src/ierror.h000066400000000000000000000104051505242054600222020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_IERROR_H #define MPD_IERROR_H #include #include #include #include #include #include /** * Structure which holds detailed information about an error, both * machine and human readable. */ struct mpd_error_info { /** * The error code of this error. None of the variables below * are valid if this is set to MPD_ERROR_SUCCESS. */ enum mpd_error code; /** * An ACK code returned by MPD. This field is only valid if * #code is MPD_ERROR_SERVER. */ enum mpd_server_error server; /** * The command list index of the command which emitted this * error. Zero if no command list was used. */ unsigned at; /** * The operating system's error code (i.e. errno or WSAGetLastError()). */ int system; /** * Human readable error message; may be NULL if not available. * This pointer is allocated on the heap, and must be freed by * calling mpd_error_clear() or mpd_error_deinit(). */ char *message; }; /** * Initialize a new mpd_error_info struct. */ static inline void mpd_error_init(struct mpd_error_info *error) { assert(error != NULL); error->code = MPD_ERROR_SUCCESS; } /** * Free memory allocated by an mpd_error_info struct. */ void mpd_error_deinit(struct mpd_error_info *error); /** * Clear the error (if any), and free its memory. */ static inline void mpd_error_clear(struct mpd_error_info *error) { mpd_error_deinit(error); error->code = MPD_ERROR_SUCCESS; } /** * Returns true if an error has occurred. */ static inline bool mpd_error_is_defined(const struct mpd_error_info *error) { return error->code != MPD_ERROR_SUCCESS; } /** * Returns true if the error is not recoverable */ static inline bool mpd_error_is_fatal(const struct mpd_error_info *error) { return error->code != MPD_ERROR_SUCCESS && error->code != MPD_ERROR_ARGUMENT && error->code != MPD_ERROR_STATE && error->code != MPD_ERROR_SERVER; } static inline const char * mpd_error_get_message(const struct mpd_error_info *error) { assert(error != NULL); assert(error->code != MPD_ERROR_SUCCESS); assert(error->message != NULL || error->code == MPD_ERROR_OOM); if (error->message == NULL) return "Out of memory"; return error->message; } /** * Sets an error code. */ static inline void mpd_error_code(struct mpd_error_info *error, enum mpd_error code) { assert(!mpd_error_is_defined(error)); error->code = code; error->message = NULL; } /** * Sets an ACK error code. */ static inline void mpd_error_server(struct mpd_error_info *error, enum mpd_server_error server, unsigned at) { mpd_error_code(error, MPD_ERROR_SERVER); error->server = server; error->at = at; } /** * Sets an system error code. */ static inline void mpd_error_system(struct mpd_error_info *error, int system_error_code) { mpd_error_code(error, MPD_ERROR_SYSTEM); error->system = system_error_code; } /** * Sets an error message. Prior to that, an error code must have been * set. */ void mpd_error_message(struct mpd_error_info *error, const char *message); /** * Sets an error message (non-terminated string with specified * length). Prior to that, an error code must have been set. */ void mpd_error_message_n(struct mpd_error_info *error, const char *message, size_t length); /** * Sets an error message (printf() like format). Prior to that, an * error code must have been set. */ mpd_printf(2, 3) void mpd_error_printf(struct mpd_error_info *error, const char *fmt, ...); /** * Sets MPD_ERROR_SYSTEM and a message provided by the OS. */ void mpd_error_system_message(struct mpd_error_info *error, int code); /** * Sets MPD_ERROR_SYSTEM and strerror(errno). */ void mpd_error_errno(struct mpd_error_info *error); /** * An entity parser has failed. The error is set depending on the * value of errno (ENOMEM or EINVAL). */ void mpd_error_entity(struct mpd_error_info *error); /** * Copies a #mpd_error_info onto another one. Duplicates the error * message. * * @return true if there was no error in #src, false if an error * condition is stored in #src (in both cases, the information is * copied) */ bool mpd_error_copy(struct mpd_error_info *dest, const struct mpd_error_info *src); #endif MusicPlayerDaemon-libmpdclient-5073329/src/internal.h000066400000000000000000000062071505242054600225210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_INTERNAL_H #define MPD_INTERNAL_H #include #include "ierror.h" /* for struct timeval */ #ifdef _WIN32 #include #else #include #endif /** * This opaque object represents a connection to a MPD server. Call * mpd_connection_new() to create a new instance. */ struct mpd_connection { /** * The initial set of settings. */ struct mpd_settings *initial_settings; /** * The connection settings in use. */ const struct mpd_settings *settings; /** * The version number received by the MPD server. */ unsigned version[3]; /** * The last error which occurred. This attribute must be * cleared with mpd_connection_clear_error() before another * command may be executed. */ struct mpd_error_info error; /** * The backend of the MPD connection. */ struct mpd_async *async; /** * The timeout for all commands. If the MPD server does not * respond within this time span, the connection is assumed to * be dead. */ struct timeval timeout; /** * The parser object used to parse response lines received * from the MPD server. */ struct mpd_parser *parser; /** * Are we currently receiving the response of a command? */ bool receiving; /** * Sending a command list right now? */ bool sending_command_list; /** * Sending a command list with "command_list_ok"? */ bool sending_command_list_ok; /** * Did the caller finish reading one sub response? * (i.e. list_OK was received, and mpd_recv_pair() has * returned NULL) */ bool discrete_finished; /** * The number of list_OK responses remaining in the command * list response. */ int command_list_remaining; /** * Declare the validity of the #pair attribute. */ enum { /** * There is no pair currently. */ PAIR_STATE_NONE, /** * The NULL pair has been enqueued with * mpd_enqueue_pair(). */ PAIR_STATE_NULL, /** * A pair has been enqueued with mpd_enqueue_pair(). */ PAIR_STATE_QUEUED, /** * There is a pair, and it has been delivered to the * caller via mpd_recv_pair(). We're waiting for him * to call mpd_return_pair(). */ PAIR_STATE_FLOATING, } pair_state; /** * The name-value pair which was "unread" with * mpd_enqueue_pair(). The special value #PAIR_NONE denotes * that this value is empty, while NULL means that somebody * "unread" the NULL pointer. */ struct mpd_pair pair; /** * The search request which is being built, committed by * mpd_search_commit(). */ char *request; }; /** * Copies the error state from connection->sync to connection->error. */ void mpd_connection_sync_error(struct mpd_connection *connection); static inline const struct timeval * mpd_connection_timeout(const struct mpd_connection *connection) { return connection->timeout.tv_sec != 0 || connection->timeout.tv_usec != 0 ? &connection->timeout : NULL; } /** * Fetches the next alternative set of settings from a settings object. * May return null. */ const struct mpd_settings * mpd_settings_get_next(const struct mpd_settings *settings); #endif MusicPlayerDaemon-libmpdclient-5073329/src/isend.h000066400000000000000000000075451505242054600220150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_ISEND_H #define MPD_ISEND_H #include struct mpd_connection; /** * Sends a command without arguments to the server, but does not * update the "receiving" flag nor the "listOks" counter. This is * used internally by the command_list functions. */ bool mpd_send_command2(struct mpd_connection *connection, const char *command); bool mpd_send_int_command(struct mpd_connection *connection, const char *command, int arg); bool mpd_send_int2_command(struct mpd_connection *connection, const char *command, int arg1, int arg2); bool mpd_send_int3_command(struct mpd_connection *connection, const char *command, int arg1, int arg2, int arg3); bool mpd_send_float_command(struct mpd_connection *connection, const char *command, float arg); bool mpd_send_u_command(struct mpd_connection *connection, const char *command, unsigned arg1); bool mpd_send_u2_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned arg2); bool mpd_send_u_f_command(struct mpd_connection *connection, const char *command, unsigned arg1, float arg2); bool mpd_send_u_s_command(struct mpd_connection *connection, const char *command, unsigned arg1, const char *arg2); bool mpd_send_s_s_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2); bool mpd_send_u_s_s_command(struct mpd_connection *connection, const char *command, unsigned arg1, const char *arg2, const char *arg3); bool mpd_send_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned arg2); bool mpd_send_s_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2, unsigned arg3); bool mpd_send_s_s_s_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2, const char *arg3, const char *arg4, unsigned arg5); bool mpd_send_range_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned arg2); /** * Send command with one string argument followed by a range argument. */ bool mpd_send_s_range_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end); /** * Send command with one integer argument followed by a range argument. */ bool mpd_send_i_range_command(struct mpd_connection *connection, const char *command, int arg1, unsigned start, unsigned end); /** * Send command with one integer argument followed by a range argument * and a to parameter. */ bool mpd_send_s_range_to_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end, char *to); bool mpd_send_s_range_to_u_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end, unsigned to); bool mpd_send_u_range_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned start, unsigned end); /** * Send command with a range argument followed by a to parameter. */ bool mpd_send_range_to_command(struct mpd_connection *connection, const char *command, unsigned start, unsigned end, const char *to); bool mpd_send_range_u_command(struct mpd_connection *connection, const char *command, unsigned start, unsigned end, unsigned arg2); bool mpd_send_u_frange_command(struct mpd_connection *connection, const char *command, unsigned arg1, float start, float end); bool mpd_send_ll_command(struct mpd_connection *connection, const char *command, long long arg); /** * Sends all pending data from the output buffer to MPD. */ bool mpd_flush(struct mpd_connection *connection); #endif MusicPlayerDaemon-libmpdclient-5073329/src/iso8601.c000066400000000000000000000051401505242054600220040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "iso8601.h" #include #include #include #ifdef _WIN32 static inline struct tm * gmtime_r(const time_t *timep, struct tm *result) { (void)result; /* Windows does not have thread-safe functions. That sucks. */ return gmtime(timep); } #endif /* _WIN32 */ /** * @return the current time zone offset in seconds */ static time_t timezone_offset(void) { const time_t t0 = 1234567890; time_t t = t0; struct tm tm_buffer, *tm; tm = gmtime_r(&t, &tm_buffer); if (tm == NULL) return 0; /* force the daylight saving time to be off; gmtime_r() should have set this already */ tm->tm_isdst = 0; t = mktime(tm); if (t == -1) return 0; return t0 - t; } /** * Unfortunately, the useful timegm() function is a GNU extension, and * mktime() returns a stamp relative to the current time zone. This * function emulates timegm() by subtracting the time zone offset, see * timezone_offset(). */ static time_t timegm_emulation(struct tm *tm) { time_t t = mktime(tm); if (t == -1) return 0; return t + timezone_offset(); } time_t iso8601_datetime_parse(const char *input) { char *endptr; int year, month, day, hour, minute, second; struct tm tm; year = strtoimax(input, &endptr, 10); if (year < 1970 || year >= 3000 || *endptr != '-') /* beware of the Y3K problem! */ return 0; input = endptr + 1; month = strtoimax(input, &endptr, 10); if (month < 1 || month > 12 || *endptr != '-') return 0; input = endptr + 1; day = strtoimax(input, &endptr, 10); if (day < 1 || day > 31 || *endptr != 'T') return 0; input = endptr + 1; hour = strtoimax(input, &endptr, 10); if (endptr == input || hour >= 24 || *endptr != ':') return 0; input = endptr + 1; minute = strtoimax(input, &endptr, 10); if (endptr == input || minute >= 60 || *endptr != ':') return 0; input = endptr + 1; second = strtoimax(input, &endptr, 10); if (endptr == input || second >= 60 || (*endptr != 0 && *endptr != 'Z')) return 0; tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; /* force the daylight saving time to be off, same as in timezone_offset() */ tm.tm_isdst = 0; return timegm_emulation(&tm); } bool iso8601_datetime_format(char *buffer, size_t size, time_t t) { struct tm tm_buffer, *tm; tm = gmtime_r(&t, &tm_buffer); if (tm == NULL) return false; #ifdef _WIN32 strftime(buffer, size, "%Y-%m-%dT%H:%M:%SZ", tm); #else strftime(buffer, size, "%FT%TZ", tm); #endif return true; } MusicPlayerDaemon-libmpdclient-5073329/src/iso8601.h000066400000000000000000000014301505242054600220070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_ISO8601_H #define MPD_ISO8601_H #include #include /** * Parses an ISO8601 time stamp to a #time_t POSIX UTC time stamp. * * @param input the ISO8601 time stamp in the form * "YYYY-MM-DDTHH:MM:SS"; it is silently assumed that the time zone is * UTC ("Z") * @return the POSIX UTC time stamp, or 0 on error */ time_t iso8601_datetime_parse(const char *input); /** * Formats a POSIX UTC time stamp into an ISO8601 string. * * @param buffer the destination string buffer * @param size the size of the buffer, including the null terminator * @return true on success, false on failure */ bool iso8601_datetime_format(char *buffer, size_t size, time_t t); #endif MusicPlayerDaemon-libmpdclient-5073329/src/kvlist.c000066400000000000000000000043761505242054600222210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "config.h" #include "kvlist.h" #include #include #include struct mpd_kvlist_item { struct mpd_kvlist_item *next; char *key, *value; }; static void mpd_kvlist_item_free(struct mpd_kvlist_item *i) { assert(i != NULL); free(i->key); free(i->value); free(i); } void mpd_kvlist_init(struct mpd_kvlist *l) { assert(l != NULL); l->head = NULL; l->tail_r = &l->head; l->cursor = NULL; } void mpd_kvlist_deinit(struct mpd_kvlist *l) { assert(l != NULL); while (l->head != NULL) { struct mpd_kvlist_item *i = l->head; l->head = i->next; mpd_kvlist_item_free(i); } } #ifndef HAVE_STRNDUP static char * strndup(const char *s, size_t length) { char *p = malloc(length + 1); if (p != NULL) { memcpy(p, s, length); p[length] = 0; } return p; } #endif void mpd_kvlist_add(struct mpd_kvlist *l, const char *key, size_t key_length, const char *value) { assert(l != NULL); assert(l->tail_r != NULL); assert(key != NULL); assert(value != NULL); struct mpd_kvlist_item *i = malloc(sizeof(*i)); if (i == NULL) return; i->next = NULL; i->key = strndup(key, key_length); i->value = strdup(value); if (i->key == NULL || i->value == NULL) { mpd_kvlist_item_free(i); return; } *l->tail_r = i; l->tail_r = &i->next; } const char * mpd_kvlist_get(const struct mpd_kvlist *l, const char *name) { for (const struct mpd_kvlist_item *i = l->head; i != NULL; i = i->next) if (strcmp(name, i->key) == 0) return i->value; return NULL; } static const struct mpd_pair * mpd_kvlist_item_to_pair(struct mpd_pair *buffer, const struct mpd_kvlist_item *item) { assert(buffer != NULL); assert(item != NULL); buffer->name = item->key; buffer->value = item->value; return buffer; } const struct mpd_pair * mpd_kvlist_first(struct mpd_kvlist *l) { assert(l != NULL); if (l->head == NULL) return NULL; l->cursor = l->head; return mpd_kvlist_item_to_pair(&l->pair, l->cursor); } const struct mpd_pair * mpd_kvlist_next(struct mpd_kvlist *l) { assert(l != NULL); assert(l->cursor != NULL); if (l->cursor->next == NULL) return NULL; l->cursor = l->cursor->next; return mpd_kvlist_item_to_pair(&l->pair, l->cursor); } MusicPlayerDaemon-libmpdclient-5073329/src/kvlist.h000066400000000000000000000013541505242054600222170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_KVLIST_H #define MPD_KVLIST_H #include #include #include struct mpd_kvlist { struct mpd_kvlist_item *head, **tail_r; const struct mpd_kvlist_item *cursor; struct mpd_pair pair; }; void mpd_kvlist_init(struct mpd_kvlist *l); void mpd_kvlist_deinit(struct mpd_kvlist *l); void mpd_kvlist_add(struct mpd_kvlist *l, const char *key, size_t key_length, const char *value); mpd_pure const char * mpd_kvlist_get(const struct mpd_kvlist *l, const char *name); const struct mpd_pair * mpd_kvlist_first(struct mpd_kvlist *l); const struct mpd_pair * mpd_kvlist_next(struct mpd_kvlist *l); #endif MusicPlayerDaemon-libmpdclient-5073329/src/list.c000066400000000000000000000030051505242054600216440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include "internal.h" #include "isend.h" #include bool mpd_command_list_begin(struct mpd_connection *connection, bool discrete_ok) { bool success; assert(connection != NULL); if (connection->sending_command_list) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "already in command list mode"); return false; } success = mpd_send_command2(connection, discrete_ok ? "command_list_ok_begin" : "command_list_begin"); if (!success) return false; connection->sending_command_list = true; connection->sending_command_list_ok = discrete_ok; connection->command_list_remaining = 0; connection->discrete_finished = false; return true; } bool mpd_command_list_end(struct mpd_connection *connection) { bool success; assert(connection != NULL); if (!connection->sending_command_list) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "not in command list mode"); return false; } connection->sending_command_list = false; success = mpd_send_command(connection, "command_list_end", NULL); /* sending_command_list will be cleared when the user requests the command list response (a function that calls mpd_recv_pair()) */ connection->sending_command_list = true; if (!success) return false; assert(connection->receiving); return true; } MusicPlayerDaemon-libmpdclient-5073329/src/message.c000066400000000000000000000023641505242054600223240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include struct mpd_message { char *channel; char *text; }; struct mpd_message * mpd_message_begin(const struct mpd_pair *pair) { struct mpd_message *output; assert(pair != NULL); if (strcmp(pair->name, "channel") != 0) return NULL; output = malloc(sizeof(*output)); if (output == NULL) return NULL; output->channel = strdup(pair->value); output->text = NULL; return output; } bool mpd_message_feed(struct mpd_message *output, const struct mpd_pair *pair) { if (strcmp(pair->name, "channel") == 0) return false; if (strcmp(pair->name, "message") == 0) { free(output->text); output->text = strdup(pair->value); } return true; } void mpd_message_free(struct mpd_message *message) { assert(message != NULL); free(message->channel); free(message->text); free(message); } const char * mpd_message_get_channel(const struct mpd_message *message) { assert(message != NULL); return message->channel; } const char * mpd_message_get_text(const struct mpd_message *message) { assert(message != NULL); return message->text; } MusicPlayerDaemon-libmpdclient-5073329/src/mixer.c000066400000000000000000000027271505242054600220270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include "isend.h" #include "run.h" #include bool mpd_send_set_volume(struct mpd_connection *connection, unsigned volume) { return mpd_send_u_command(connection, "setvol", volume); } bool mpd_run_set_volume(struct mpd_connection *connection, unsigned volume) { return mpd_run_check(connection) && mpd_send_set_volume(connection, volume) && mpd_response_finish(connection); } bool mpd_send_change_volume(struct mpd_connection *connection, int relative_volume) { return mpd_send_int_command(connection, "volume", relative_volume); } bool mpd_run_change_volume(struct mpd_connection *connection, int relative_volume) { return mpd_run_check(connection) && mpd_send_change_volume(connection, relative_volume) && mpd_response_finish(connection); } bool mpd_send_get_volume(struct mpd_connection *connection) { return mpd_send_command(connection, "getvol", NULL); } int mpd_run_get_volume(struct mpd_connection *connection) { if (!mpd_run_check(connection) || !mpd_send_get_volume(connection)) return -1; int result = -1; struct mpd_pair *pair = mpd_recv_pair_named(connection, "volume"); if (pair != NULL) { result = atoi(pair->value); mpd_return_pair(connection, pair); } if (!mpd_response_finish(connection)) result = -1; return result; } MusicPlayerDaemon-libmpdclient-5073329/src/mount.c000066400000000000000000000023251505242054600220370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include struct mpd_mount { char *uri; char *storage; }; struct mpd_mount * mpd_mount_begin(const struct mpd_pair *pair) { assert(pair != NULL); if (strcmp(pair->name, "mount") != 0) return NULL; struct mpd_mount *mount = malloc(sizeof(*mount)); if (mount == NULL) return NULL; mount->uri = strdup(pair->value); if (mount->uri == NULL) { free(mount); return NULL; } mount->storage = NULL; return mount; } bool mpd_mount_feed(struct mpd_mount *mount, const struct mpd_pair *pair) { if (strcmp(pair->name, "mount") == 0) return false; if (strcmp(pair->name, "storage") == 0) { free(mount->storage); mount->storage = strdup(pair->value); } return true; } void mpd_mount_free(struct mpd_mount *mount) { assert(mount != NULL); free(mount->uri); free(mount->storage); free(mount); } const char * mpd_mount_get_uri(const struct mpd_mount *mount) { assert(mount != NULL); return mount->uri; } const char * mpd_mount_get_storage(const struct mpd_mount *mount) { assert(mount != NULL); return mount->storage; } MusicPlayerDaemon-libmpdclient-5073329/src/neighbor.c000066400000000000000000000025441505242054600224750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include struct mpd_neighbor { char *uri; char *display_name; }; struct mpd_neighbor * mpd_neighbor_begin(const struct mpd_pair *pair) { assert(pair != NULL); if (strcmp(pair->name, "neighbor") != 0) return NULL; struct mpd_neighbor *neighbor = malloc(sizeof(*neighbor)); if (neighbor == NULL) return NULL; neighbor->uri = strdup(pair->value); if (neighbor->uri == NULL) { free(neighbor); return NULL; } neighbor->display_name = NULL; return neighbor; } bool mpd_neighbor_feed(struct mpd_neighbor *neighbor, const struct mpd_pair *pair) { if (strcmp(pair->name, "neighbor") == 0) return false; if (strcmp(pair->name, "name") == 0) { free(neighbor->display_name); neighbor->display_name = strdup(pair->value); } return true; } void mpd_neighbor_free(struct mpd_neighbor *neighbor) { assert(neighbor != NULL); free(neighbor->uri); free(neighbor->display_name); free(neighbor); } const char * mpd_neighbor_get_uri(const struct mpd_neighbor *neighbor) { assert(neighbor != NULL); return neighbor->uri; } const char * mpd_neighbor_get_display_name(const struct mpd_neighbor *neighbor) { assert(neighbor != NULL); return neighbor->display_name; } MusicPlayerDaemon-libmpdclient-5073329/src/output.c000066400000000000000000000050451505242054600222370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include "kvlist.h" #include #include #include struct mpd_output { unsigned id; char *name; char *plugin; struct mpd_kvlist attributes; bool enabled; }; struct mpd_output * mpd_output_begin(const struct mpd_pair *pair) { struct mpd_output *output; assert(pair != NULL); if (strcmp(pair->name, "outputid") != 0) return NULL; output = malloc(sizeof(*output)); if (output == NULL) return NULL; output->id = strtoul(pair->value, NULL, 10); output->name = NULL; output->plugin = NULL; mpd_kvlist_init(&output->attributes); output->enabled = false; return output; } bool mpd_output_feed(struct mpd_output *output, const struct mpd_pair *pair) { if (strcmp(pair->name, "outputid") == 0) return false; if (strcmp(pair->name, "outputname") == 0) { free(output->name); output->name = strdup(pair->value); } else if (strcmp(pair->name, "outputenabled") == 0) output->enabled = atoi(pair->value) != 0; else if (strcmp(pair->name, "plugin") == 0) { free(output->plugin); output->plugin = strdup(pair->value); } else if (strcmp(pair->name, "attribute") == 0) { const char *eq = strchr(pair->value, '='); if (eq != NULL && eq > pair->value) mpd_kvlist_add(&output->attributes, pair->value, eq - pair->value, eq + 1); } return true; } void mpd_output_free(struct mpd_output *output) { assert(output != NULL); free(output->name); free(output->plugin); mpd_kvlist_deinit(&output->attributes); free(output); } unsigned mpd_output_get_id(const struct mpd_output *output) { assert(output != NULL); return output->id; } const char * mpd_output_get_name(const struct mpd_output *output) { assert(output != NULL); return output->name; } const char * mpd_output_get_plugin(const struct mpd_output *output) { assert(output != NULL); return output->plugin; } bool mpd_output_get_enabled(const struct mpd_output *output) { assert(output != NULL); return output->enabled; } const char * mpd_output_get_attribute(const struct mpd_output *output, const char *name) { assert(output != NULL); return mpd_kvlist_get(&output->attributes, name); } const struct mpd_pair * mpd_output_first_attribute(struct mpd_output *output) { assert(output != NULL); return mpd_kvlist_first(&output->attributes); } const struct mpd_pair * mpd_output_next_attribute(struct mpd_output *output) { assert(output != NULL); return mpd_kvlist_next(&output->attributes); } MusicPlayerDaemon-libmpdclient-5073329/src/parser.c000066400000000000000000000065711505242054600222000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include struct mpd_parser { #ifndef NDEBUG /** * This is used by assertions in the "get" functions below. */ enum mpd_parser_result result; #endif union { bool discrete; struct { enum mpd_server_error server; unsigned at; const char *message; } error; struct { const char *name, *value; } pair; } u; }; struct mpd_parser * mpd_parser_new(void) { struct mpd_parser *parser = malloc(sizeof(*parser)); if (parser == NULL) return NULL; #ifndef NDEBUG parser->result = MPD_PARSER_MALFORMED; #endif return parser; } void mpd_parser_free(struct mpd_parser *parser) { free(parser); } static inline enum mpd_parser_result set_result(struct mpd_parser *parser, enum mpd_parser_result result) { #ifndef NDEBUG /* this value exists only in the debug build, and is used by assertions in the "get" functions below */ parser->result = result; #else /* suppress "unused" warning */ (void)parser; #endif return result; } enum mpd_parser_result mpd_parser_feed(struct mpd_parser *parser, char *line) { if (strcmp(line, "OK") == 0) { parser->u.discrete = false; return set_result(parser, MPD_PARSER_SUCCESS); } else if (strcmp(line, "list_OK") == 0) { parser->u.discrete = true; return set_result(parser, MPD_PARSER_SUCCESS); } else if (memcmp(line, "ACK", 3) == 0) { char *p, *q; parser->u.error.server = MPD_SERVER_ERROR_UNK; parser->u.error.at = 0; parser->u.error.message = NULL; /* parse [ACK@AT] */ p = strchr(line + 3, '['); if (p == NULL) return set_result(parser, MPD_PARSER_ERROR); parser->u.error.server = strtol(p + 1, &p, 10); if (*p == '@') parser->u.error.at = strtoul(p + 1, &p, 10); q = strchr(p, ']'); if (q == NULL) return set_result(parser, MPD_PARSER_MALFORMED); /* skip the {COMMAND} */ p = q + 1; q = strchr(p, '{'); if (q != NULL) { q = strchr(p, '}'); if (q != NULL) p = q + 1; } /* obtain error message */ while (*p == ' ') ++p; if (*p != 0) parser->u.error.message = p; return set_result(parser, MPD_PARSER_ERROR); } else { /* so this must be a name-value pair */ char *p; p = strchr(line, ':'); if (p == NULL || p[1] != ' ') return set_result(parser, MPD_PARSER_MALFORMED); *p = 0; parser->u.pair.name = line; parser->u.pair.value = p + 2; return set_result(parser, MPD_PARSER_PAIR); } } bool mpd_parser_is_discrete(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_SUCCESS); return parser->u.discrete; } enum mpd_server_error mpd_parser_get_server_error(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_ERROR); return parser->u.error.server; } unsigned mpd_parser_get_at(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_ERROR); return parser->u.error.at; } const char * mpd_parser_get_message(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_ERROR); return parser->u.error.message; } const char * mpd_parser_get_name(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_PAIR); return parser->u.pair.name; } const char * mpd_parser_get_value(const struct mpd_parser *parser) { assert(parser->result == MPD_PARSER_PAIR); return parser->u.pair.value; } MusicPlayerDaemon-libmpdclient-5073329/src/partition.c000066400000000000000000000016331505242054600227070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include struct mpd_partition { char *name; }; struct mpd_partition * mpd_partition_new(const struct mpd_pair *pair) { assert(pair != NULL); if (strcmp(pair->name, "partition") != 0) return NULL; struct mpd_partition *partition = malloc(sizeof(*partition)); if (partition == NULL) return NULL; partition->name = strdup(pair->value); if (partition->name == NULL) { free(partition); return NULL; } return partition; } void mpd_partition_free(struct mpd_partition *partition) { assert(partition != NULL); free(partition->name); free(partition); } mpd_pure const char * mpd_partition_get_name(const struct mpd_partition *partition) { assert(partition != NULL); return partition->name; } MusicPlayerDaemon-libmpdclient-5073329/src/password.c000066400000000000000000000010501505242054600225310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include "run.h" #include bool mpd_send_password(struct mpd_connection *connection, const char *password) { return mpd_send_command(connection, "password", password, NULL); } bool mpd_run_password(struct mpd_connection *connection, const char *password) { return mpd_run_check(connection) && mpd_send_password(connection, password) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/player.c000066400000000000000000000207531505242054600221760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "isend.h" #include "run.h" #include "config.h" // for HAVE_USELOCALE #include #include #ifdef HAVE_USELOCALE #include #endif bool mpd_send_current_song(struct mpd_connection *connection) { return mpd_send_command(connection, "currentsong", NULL); } struct mpd_song * mpd_run_current_song(struct mpd_connection *connection) { struct mpd_song *song; if (!mpd_run_check(connection) || !mpd_send_current_song(connection)) return NULL; song = mpd_recv_song(connection); if (song == NULL) return NULL; if (!mpd_response_finish(connection)) { mpd_song_free(song); return NULL; } return song; } bool mpd_send_play(struct mpd_connection *connection) { return mpd_send_command(connection, "play", NULL); } bool mpd_run_play(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_play(connection) && mpd_response_finish(connection); } bool mpd_send_play_pos(struct mpd_connection *connection, unsigned song_pos) { return mpd_send_u_command(connection, "play", song_pos); } bool mpd_run_play_pos(struct mpd_connection *connection, unsigned song_pos) { return mpd_run_check(connection) && mpd_send_play_pos(connection, song_pos) && mpd_response_finish(connection); } bool mpd_send_play_id(struct mpd_connection *connection, unsigned song_id) { return mpd_send_u_command(connection, "playid", song_id); } bool mpd_run_play_id(struct mpd_connection *connection, unsigned song_id) { return mpd_run_check(connection) && mpd_send_play_id(connection, song_id) && mpd_response_finish(connection); } bool mpd_send_stop(struct mpd_connection *connection) { return mpd_send_command(connection, "stop", NULL); } bool mpd_run_stop(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_stop(connection) && mpd_response_finish(connection); } bool mpd_send_toggle_pause(struct mpd_connection *connection) { return mpd_send_command(connection, "pause", NULL); } bool mpd_run_toggle_pause(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_toggle_pause(connection) && mpd_response_finish(connection); } bool mpd_send_pause(struct mpd_connection *connection, bool mode) { return mpd_send_int_command(connection, "pause", mode); } bool mpd_run_pause(struct mpd_connection *connection, bool mode) { return mpd_run_check(connection) && mpd_send_pause(connection, mode) && mpd_response_finish(connection); } bool mpd_send_next(struct mpd_connection *connection) { return mpd_send_command(connection, "next", NULL); } bool mpd_run_next(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_next(connection) && mpd_response_finish(connection); } bool mpd_send_previous(struct mpd_connection *connection) { return mpd_send_command(connection, "previous", NULL); } bool mpd_run_previous(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_previous(connection) && mpd_response_finish(connection); } bool mpd_send_seek_pos(struct mpd_connection *connection, unsigned song_pos, unsigned t) { return mpd_send_u2_command(connection, "seek", song_pos, t); } bool mpd_run_seek_pos(struct mpd_connection *connection, unsigned song_pos, unsigned t) { return mpd_run_check(connection) && mpd_send_seek_pos(connection, song_pos, t) && mpd_response_finish(connection); } bool mpd_send_seek_id(struct mpd_connection *connection, unsigned song_id, unsigned t) { return mpd_send_u2_command(connection, "seekid", song_id, t); } bool mpd_run_seek_id(struct mpd_connection *connection, unsigned song_id, unsigned t) { return mpd_run_check(connection) && mpd_send_seek_id(connection, song_id, t) && mpd_response_finish(connection); } bool mpd_send_seek_id_float(struct mpd_connection *connection, unsigned song_id, float t) { return mpd_send_u_f_command(connection, "seekid", song_id, t); } bool mpd_run_seek_id_float(struct mpd_connection *connection, unsigned song_id, float t) { return mpd_run_check(connection) && mpd_send_seek_id_float(connection, song_id, t) && mpd_response_finish(connection); } bool mpd_send_seek_current(struct mpd_connection *connection, float t, bool relative) { #ifdef HAVE_USELOCALE // use the POSIX locale to format floating point numbers const locale_t my_locale = newlocale(LC_NUMERIC_MASK, "C", NULL); const locale_t old_locale = uselocale(my_locale); #endif char ts[32]; if (relative) snprintf(ts, sizeof(ts), "%+.3f", (double)t); else snprintf(ts, sizeof(ts), "%.3f", (double)t); #ifdef HAVE_USELOCALE uselocale(old_locale); freelocale(my_locale); #endif return mpd_send_command(connection, "seekcur", ts, NULL); } bool mpd_run_seek_current(struct mpd_connection *connection, float t, bool relative) { return mpd_run_check(connection) && mpd_send_seek_current(connection, t, relative) && mpd_response_finish(connection); } bool mpd_send_repeat(struct mpd_connection *connection, bool mode) { return mpd_send_int_command(connection, "repeat", mode); } bool mpd_run_repeat(struct mpd_connection *connection, bool mode) { return mpd_run_check(connection) && mpd_send_repeat(connection, mode) && mpd_response_finish(connection); } bool mpd_send_random(struct mpd_connection *connection, bool mode) { return mpd_send_int_command(connection, "random", mode); } bool mpd_run_random(struct mpd_connection *connection, bool mode) { return mpd_run_check(connection) && mpd_send_random(connection, mode) && mpd_response_finish(connection); } bool mpd_send_single_state(struct mpd_connection *connection, enum mpd_single_state state) { const char *state_str = mpd_lookup_single_state(state); if (state_str == NULL) return false; return mpd_send_command(connection, "single", state_str, NULL); } bool mpd_run_single_state(struct mpd_connection *connection, enum mpd_single_state state) { return mpd_run_check(connection) && mpd_send_single_state(connection, state) && mpd_response_finish(connection); } bool mpd_send_single(struct mpd_connection *connection, bool mode) { return mpd_send_int_command(connection, "single", mode); } bool mpd_run_single(struct mpd_connection *connection, bool mode) { return mpd_run_check(connection) && mpd_send_single(connection, mode) && mpd_response_finish(connection); } bool mpd_send_consume_state(struct mpd_connection *connection, enum mpd_consume_state state) { const char *state_str = mpd_lookup_consume_state(state); if (state_str == NULL) return false; return mpd_send_command(connection, "consume", state_str, NULL); } bool mpd_run_consume_state(struct mpd_connection *connection, enum mpd_consume_state state) { return mpd_run_check(connection) && mpd_send_consume_state(connection, state) && mpd_response_finish(connection); } bool mpd_send_consume(struct mpd_connection *connection, bool mode) { return mpd_send_int_command(connection, "consume", mode); } bool mpd_run_consume(struct mpd_connection *connection, bool mode) { return mpd_run_check(connection) && mpd_send_consume(connection, mode) && mpd_response_finish(connection); } bool mpd_send_crossfade(struct mpd_connection *connection, unsigned seconds) { return mpd_send_u_command(connection, "crossfade", seconds); } bool mpd_run_crossfade(struct mpd_connection *connection, unsigned seconds) { return mpd_run_check(connection) && mpd_send_crossfade(connection, seconds) && mpd_response_finish(connection); } bool mpd_send_mixrampdb(struct mpd_connection *connection, float db) { return mpd_send_float_command(connection, "mixrampdb", db); } bool mpd_run_mixrampdb(struct mpd_connection *connection, float db) { return mpd_run_check(connection) && mpd_send_mixrampdb(connection, db) && mpd_response_finish(connection); } bool mpd_send_mixrampdelay(struct mpd_connection *connection, float seconds) { return mpd_send_float_command(connection, "mixrampdelay", seconds); } bool mpd_run_mixrampdelay(struct mpd_connection *connection, float seconds) { return mpd_run_check(connection) && mpd_send_mixrampdelay(connection, seconds) && mpd_response_finish(connection); } bool mpd_send_clearerror(struct mpd_connection *connection) { return mpd_send_command(connection, "clearerror", NULL); } bool mpd_run_clearerror(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_clearerror(connection) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/playlist.c000066400000000000000000000042221505242054600225340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include "iso8601.h" #include "uri.h" #include #include #include #include struct mpd_playlist { char *path; /** * The POSIX UTC time stamp of the last modification, or 0 if * that is unknown. */ time_t last_modified; }; static struct mpd_playlist * mpd_playlist_new(const char *path) { struct mpd_playlist *playlist; assert(path != NULL); assert(mpd_verify_local_uri(path)); playlist = malloc(sizeof(*playlist)); if (playlist == NULL) /* out of memory */ return NULL; playlist->path = strdup(path); if (playlist->path == NULL) { /* out of memory */ free(playlist); return NULL; } playlist->last_modified = 0; return playlist; } void mpd_playlist_free(struct mpd_playlist *playlist) { assert(playlist != NULL); assert(playlist->path != NULL); free(playlist->path); free(playlist); } struct mpd_playlist * mpd_playlist_dup(const struct mpd_playlist *playlist) { assert(playlist != NULL); assert(playlist->path != NULL); struct mpd_playlist *copy = mpd_playlist_new(playlist->path); copy->last_modified = playlist->last_modified; return copy; } const char * mpd_playlist_get_path(const struct mpd_playlist *playlist) { assert(playlist != NULL); return playlist->path; } time_t mpd_playlist_get_last_modified(const struct mpd_playlist *playlist) { return playlist->last_modified; } struct mpd_playlist * mpd_playlist_begin(const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "playlist") != 0 || !mpd_verify_local_uri(pair->value)) { errno = EINVAL; return NULL; } return mpd_playlist_new(pair->value); } bool mpd_playlist_feed(struct mpd_playlist *playlist, const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "playlist") == 0) return false; if (strcmp(pair->name, "Last-Modified") == 0) playlist->last_modified = iso8601_datetime_parse(pair->value); return true; } MusicPlayerDaemon-libmpdclient-5073329/src/position.c000066400000000000000000000005141505242054600225370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include const char * mpd_position_whence_char(enum mpd_position_whence whence) { switch (whence) { case MPD_POSITION_AFTER_CURRENT: return "+"; case MPD_POSITION_BEFORE_CURRENT: return "-"; default: return ""; } } MusicPlayerDaemon-libmpdclient-5073329/src/queue.c000066400000000000000000000341521505242054600220240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "internal.h" #include "isend.h" #include "run.h" #include #include #include bool mpd_send_list_queue_meta(struct mpd_connection *connection) { return mpd_send_command(connection, "playlistinfo", NULL); } bool mpd_send_list_queue_range_meta(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_send_range_command(connection, "playlistinfo", start, end); } bool mpd_send_get_queue_song_pos(struct mpd_connection *connection, unsigned pos) { return mpd_send_u_command(connection, "playlistinfo", pos); } struct mpd_song * mpd_run_get_queue_song_pos(struct mpd_connection *connection, unsigned pos) { struct mpd_song *song; if (!mpd_run_check(connection) || !mpd_send_get_queue_song_pos(connection, pos)) return NULL; song = mpd_recv_song(connection); if (!mpd_response_finish(connection) && song != NULL) { mpd_song_free(song); return NULL; } return song; } bool mpd_send_get_queue_song_id(struct mpd_connection *connection, unsigned id) { return mpd_send_u_command(connection, "playlistid", id); } struct mpd_song * mpd_run_get_queue_song_id(struct mpd_connection *connection, unsigned id) { struct mpd_song *song; if (!mpd_run_check(connection) || !mpd_send_get_queue_song_id(connection, id)) return NULL; song = mpd_recv_song(connection); if (!mpd_response_finish(connection) && song != NULL) { mpd_song_free(song); return NULL; } return song; } bool mpd_send_queue_changes_meta(struct mpd_connection *connection, unsigned version) { return mpd_send_u_command(connection, "plchanges", version); } bool mpd_send_queue_changes_meta_range(struct mpd_connection *connection, unsigned version, unsigned start, unsigned end) { return mpd_send_u_range_command(connection, "plchanges", version, start, end); } bool mpd_send_queue_changes_brief(struct mpd_connection *connection, unsigned version) { return mpd_send_u_command(connection, "plchangesposid", version); } bool mpd_send_queue_changes_brief_range(struct mpd_connection *connection, unsigned version, unsigned start, unsigned end) { return mpd_send_u_range_command(connection, "plchangesposid", version, start, end); } bool mpd_recv_queue_change_brief(struct mpd_connection *connection, unsigned *position_r, unsigned *id_r) { struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "cpos"); if (pair == NULL) return false; *position_r = strtoul(pair->value, NULL, 10); mpd_return_pair(connection, pair); pair = mpd_recv_pair_named(connection, "Id"); if (pair == NULL) { mpd_return_pair(connection, pair); if (!mpd_error_is_defined(&connection->error)) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "No id received"); } return false; } *id_r = strtoul(pair->value, NULL, 10); mpd_return_pair(connection, pair); return !mpd_error_is_defined(&connection->error); } bool mpd_send_add(struct mpd_connection *connection, const char *uri) { return mpd_send_command(connection, "add", uri, NULL); } bool mpd_run_add(struct mpd_connection *connection, const char *uri) { return mpd_run_check(connection) && mpd_send_add(connection, uri) && mpd_response_finish(connection); } bool mpd_send_add_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_s_s_command(connection, "add", uri, to_str); } bool mpd_run_add_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence) { return mpd_run_check(connection) && mpd_send_add_whence(connection, uri, to, whence) && mpd_response_finish(connection); } bool mpd_send_add_id(struct mpd_connection *connection, const char *uri) { return mpd_send_command(connection, "addid", uri, NULL); } bool mpd_send_add_id_to(struct mpd_connection *connection, const char *uri, unsigned to) { return mpd_send_s_u_command(connection, "addid", uri, to); } bool mpd_send_add_id_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_s_s_command(connection, "addid", uri, to_str); } int mpd_recv_song_id(struct mpd_connection *connection) { struct mpd_pair *pair; int id = -1; pair = mpd_recv_pair_named(connection, "Id"); if (pair != NULL) { id = atoi(pair->value); mpd_return_pair(connection, pair); } return id; } int mpd_run_add_id(struct mpd_connection *connection, const char *uri) { int id; if (!mpd_run_check(connection) || !mpd_send_add_id(connection, uri)) return -1; id = mpd_recv_song_id(connection); if (!mpd_response_finish(connection)) id = -1; return id; } int mpd_run_add_id_to(struct mpd_connection *connection, const char *uri, unsigned to) { int id; if (!mpd_run_check(connection) || !mpd_send_add_id_to(connection, uri, to)) return -1; id = mpd_recv_song_id(connection); if (!mpd_response_finish(connection)) id = -1; return id; } int mpd_run_add_id_whence(struct mpd_connection *connection, const char *uri, unsigned to, enum mpd_position_whence whence) { int id; if (!mpd_run_check(connection) || !mpd_send_add_id_whence(connection, uri, to, whence)) return -1; id = mpd_recv_song_id(connection); if (!mpd_response_finish(connection)) id = -1; return id; } bool mpd_send_delete(struct mpd_connection *connection, unsigned pos) { return mpd_send_u_command(connection, "delete", pos); } bool mpd_run_delete(struct mpd_connection *connection, unsigned pos) { return mpd_run_check(connection) && mpd_send_delete(connection, pos) && mpd_response_finish(connection); } bool mpd_send_delete_range(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_send_range_command(connection, "delete", start, end); } bool mpd_run_delete_range(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_run_check(connection) && mpd_send_delete_range(connection, start, end) && mpd_response_finish(connection); } bool mpd_send_delete_id(struct mpd_connection *connection, unsigned id) { return mpd_send_u_command(connection, "deleteid", id); } bool mpd_run_delete_id(struct mpd_connection *connection, unsigned id) { return mpd_run_check(connection) && mpd_send_delete_id(connection, id) && mpd_response_finish(connection); } bool mpd_send_shuffle(struct mpd_connection *connection) { return mpd_send_command(connection, "shuffle", NULL); } bool mpd_run_shuffle(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_shuffle(connection) && mpd_response_finish(connection); } bool mpd_send_shuffle_range(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_send_range_command(connection, "shuffle", start, end); } bool mpd_run_shuffle_range(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_run_check(connection) && mpd_send_shuffle_range(connection, start, end) && mpd_response_finish(connection); } bool mpd_send_clear(struct mpd_connection *connection) { return mpd_send_command(connection, "clear", NULL); } bool mpd_run_clear(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_clear(connection) && mpd_response_finish(connection); } bool mpd_send_move(struct mpd_connection *connection, unsigned from, unsigned to) { return mpd_send_u2_command(connection, "move", from, to); } bool mpd_run_move(struct mpd_connection *connection, unsigned from, unsigned to) { return mpd_run_check(connection) && mpd_send_move(connection, from, to) && mpd_response_finish(connection); } bool mpd_send_move_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_u_s_command(connection, "move", from, to_str); } bool mpd_run_move_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence) { return mpd_run_check(connection) && mpd_send_move_whence(connection, from, to, whence) && mpd_response_finish(connection); } bool mpd_send_move_id(struct mpd_connection *connection, unsigned from, unsigned to) { return mpd_send_u2_command(connection, "moveid", from, to); } bool mpd_run_move_id(struct mpd_connection *connection, unsigned from, unsigned to) { return mpd_run_check(connection) && mpd_send_move_id(connection, from, to) && mpd_response_finish(connection); } bool mpd_send_move_id_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_u_s_command(connection, "moveid", from, to_str); } bool mpd_run_move_id_whence(struct mpd_connection *connection, unsigned from, unsigned to, enum mpd_position_whence whence) { return mpd_run_check(connection) && mpd_send_move_id_whence(connection, from, to, whence) && mpd_response_finish(connection); } bool mpd_send_move_range(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to) { return mpd_send_range_u_command(connection, "move", start, end, to); } bool mpd_run_move_range(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to) { return mpd_run_check(connection) && mpd_send_move_range(connection, start, end, to) && mpd_response_finish(connection); } bool mpd_send_move_range_whence(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence) { const char *whence_s = mpd_position_whence_char(whence); char to_str[64] = ""; snprintf(to_str, 64, "%s%u", whence_s, to); return mpd_send_range_to_command(connection, "move", start, end, to_str); } bool mpd_run_move_range_whence(struct mpd_connection *connection, unsigned start, unsigned end, unsigned to, enum mpd_position_whence whence) { return mpd_run_check(connection) && mpd_send_move_range_whence(connection, start, end, to, whence) && mpd_response_finish(connection); } bool mpd_send_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2) { return mpd_send_u2_command(connection, "swap", pos1, pos2); } bool mpd_run_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2) { return mpd_run_check(connection) && mpd_send_swap(connection, pos1, pos2) && mpd_response_finish(connection); } bool mpd_send_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2) { return mpd_send_u2_command(connection, "swapid", id1, id2); } bool mpd_run_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2) { return mpd_run_check(connection) && mpd_send_swap_id(connection, id1, id2) && mpd_response_finish(connection); } bool mpd_send_add_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag, const char *value) { return mpd_send_u_s_s_command(connection, "addtagid", id, mpd_tag_name(tag), value); } bool mpd_run_add_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag, const char *value) { return mpd_run_check(connection) && mpd_send_add_tag_id(connection, id, tag, value) && mpd_response_finish(connection); } bool mpd_send_clear_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag) { return mpd_send_u_s_command(connection, "cleartagid", id, mpd_tag_name(tag)); } bool mpd_run_clear_tag_id(struct mpd_connection *connection, unsigned id, enum mpd_tag_type tag) { return mpd_run_check(connection) && mpd_send_clear_tag_id(connection, id, tag) && mpd_response_finish(connection); } bool mpd_send_clear_all_tags_id(struct mpd_connection *connection, unsigned id) { return mpd_send_u_command(connection, "cleartagid", id); } bool mpd_run_clear_all_tags_id(struct mpd_connection *connection, unsigned id) { return mpd_run_check(connection) && mpd_send_clear_all_tags_id(connection, id) && mpd_response_finish(connection); } bool mpd_send_prio(struct mpd_connection *connection, unsigned priority, unsigned position) { return mpd_send_u2_command(connection, "prio", priority, position); } bool mpd_run_prio(struct mpd_connection *connection, unsigned priority, unsigned position) { return mpd_run_check(connection) && mpd_send_prio(connection, priority, position) && mpd_response_finish(connection); } bool mpd_send_prio_range(struct mpd_connection *connection, unsigned priority, unsigned start, unsigned end) { return mpd_send_u_range_command(connection, "prio", priority, start, end); } bool mpd_run_prio_range(struct mpd_connection *connection, unsigned priority, unsigned start, unsigned end) { return mpd_run_check(connection) && mpd_send_prio_range(connection, priority, start, end) && mpd_response_finish(connection); } bool mpd_send_prio_id(struct mpd_connection *connection, unsigned priority, unsigned id) { return mpd_send_u2_command(connection, "prioid", priority, id); } bool mpd_run_prio_id(struct mpd_connection *connection, unsigned priority, unsigned id) { return mpd_run_check(connection) && mpd_send_prio_id(connection, priority, id) && mpd_response_finish(connection); } bool mpd_send_range_id(struct mpd_connection *connection, unsigned id, float start, float end) { return mpd_send_u_frange_command(connection, "rangeid", id, start, end); } bool mpd_run_range_id(struct mpd_connection *connection, unsigned id, float start, float end) { return mpd_run_check(connection) && mpd_send_range_id(connection, id, start, end) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/quote.c000066400000000000000000000013021505242054600220240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include "quote.h" #include /** * Append a string to the buffer, and escape special characters. */ static char * escape(char *dest, char *end, const char *value) { while (*value != 0) { char ch = *value++; if (dest >= end) return NULL; if (ch == '"' || ch == '\\') { *dest++ = '\\'; if (dest >= end) return NULL; } *dest++ = ch; } return dest; } char * quote(char *dest, char *end, const char *value) { if (dest >= end) return NULL; *dest++ = '"'; dest = escape(dest, end, value); if (dest == NULL || dest >= end) return NULL; *dest++ = '"'; return dest; } MusicPlayerDaemon-libmpdclient-5073329/src/quote.h000066400000000000000000000007461505242054600220440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #ifndef MPD_QUOTE_H #define MPD_QUOTE_H /** * Enclose a string in double quotes, and escape special characters. * * @param dest the destination buffer * @param end the end of the destination buffer (pointer to the first * invalid byte) * @param value the string to quote * @return a pointer to the end of the quoted string */ char * quote(char *dest, char *end, const char *value); #endif MusicPlayerDaemon-libmpdclient-5073329/src/rdirectory.c000066400000000000000000000016701505242054600230650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include "internal.h" #include struct mpd_directory * mpd_recv_directory(struct mpd_connection *connection) { struct mpd_pair *pair; struct mpd_directory *directory; pair = mpd_recv_pair_named(connection, "directory"); if (pair == NULL) return NULL; directory = mpd_directory_begin(pair); mpd_return_pair(connection, pair); if (directory == NULL) { mpd_error_entity(&connection->error); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_directory_feed(directory, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_directory_free(directory); return NULL; } /* unread this pair for the next mpd_recv_directory() call */ mpd_enqueue_pair(connection, pair); return directory; } MusicPlayerDaemon-libmpdclient-5073329/src/readpicture.c000066400000000000000000000026271505242054600232110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "run.h" #include "internal.h" #include "sync.h" #include "isend.h" #include #include #include bool mpd_send_readpicture(struct mpd_connection *connection, const char *uri, unsigned offset) { return mpd_send_s_u_command(connection, "readpicture", uri, offset); } int mpd_recv_readpicture(struct mpd_connection *connection, void *buffer, size_t buffer_size) { struct mpd_pair *pair = mpd_recv_pair_named(connection, "binary"); if (pair == NULL) { return -1; } size_t chunk_size = strtoumax(pair->value, NULL, 10); mpd_return_pair(connection, pair); size_t retrieve_bytes = chunk_size > buffer_size ? buffer_size : chunk_size; if (mpd_recv_binary(connection, buffer, retrieve_bytes) == false) { return -1; } return (int)retrieve_bytes; } int mpd_run_readpicture(struct mpd_connection *connection, const char *uri, unsigned offset, void *buffer, size_t buffer_size) { if (!mpd_run_check(connection) || !mpd_send_readpicture(connection, uri, offset)) { return -1; } int read_size = mpd_recv_readpicture(connection, buffer, buffer_size); if (!mpd_response_finish(connection)) { return -1; } return read_size; } MusicPlayerDaemon-libmpdclient-5073329/src/recv.c000066400000000000000000000126411505242054600216360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include "internal.h" #include "iasync.h" #include "sync.h" #include #include bool mpd_recv_binary(struct mpd_connection *connection, void *data, size_t length) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return false; /* check if the caller has returned the previous pair */ assert(connection->pair_state != PAIR_STATE_FLOATING); while (length > 0) { size_t nbytes = mpd_sync_recv_raw(connection->async, mpd_connection_timeout(connection), data, length); if (nbytes == 0) { mpd_connection_sync_error(connection); return false; } data = ((char *)data) + nbytes; length -= nbytes; } char newline; if (mpd_sync_recv_raw(connection->async, mpd_connection_timeout(connection), &newline, sizeof(newline)) == 0) { mpd_connection_sync_error(connection); return false; } if (newline != '\n') { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "Malformed binary response"); return false; } return true; } struct mpd_pair * mpd_recv_pair(struct mpd_connection *connection) { struct mpd_pair *pair; char *line; enum mpd_parser_result result; const char *msg; assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return NULL; /* check if the caller has returned the previous pair */ assert(connection->pair_state != PAIR_STATE_FLOATING); if (connection->pair_state == PAIR_STATE_NULL) { /* return the enqueued NULL pair */ connection->pair_state = PAIR_STATE_NONE; return NULL; } if (connection->pair_state == PAIR_STATE_QUEUED) { /* dequeue the pair from mpd_enqueue_pair() */ pair = &connection->pair; connection->pair_state = PAIR_STATE_FLOATING; return pair; } assert(connection->pair_state == PAIR_STATE_NONE); if (!connection->receiving || (connection->sending_command_list && connection->command_list_remaining > 0 && connection->discrete_finished)) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "already done processing current command"); return NULL; } line = mpd_sync_recv_line(connection->async, mpd_connection_timeout(connection)); if (line == NULL) { connection->receiving = false; connection->sending_command_list = false; mpd_connection_sync_error(connection); return NULL; } result = mpd_parser_feed(connection->parser, line); switch (result) { case MPD_PARSER_MALFORMED: mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "Failed to parse MPD response"); connection->receiving = false; return NULL; case MPD_PARSER_SUCCESS: if (!mpd_parser_is_discrete(connection->parser)) { if (connection->sending_command_list && connection->command_list_remaining > 0) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "expected more list_OK's"); connection->command_list_remaining = 0; } connection->receiving = false; connection->sending_command_list = false; connection->discrete_finished = false; } else { if (!connection->sending_command_list || connection->command_list_remaining == 0) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "got an unexpected list_OK"); } else { connection->discrete_finished = true; --connection->command_list_remaining; } } return NULL; case MPD_PARSER_ERROR: connection->receiving = false; connection->sending_command_list = false; mpd_error_server(&connection->error, mpd_parser_get_server_error(connection->parser), mpd_parser_get_at(connection->parser)); msg = mpd_parser_get_message(connection->parser); if (msg == NULL) msg = "Unspecified MPD error"; mpd_error_message(&connection->error, msg); return NULL; case MPD_PARSER_PAIR: pair = &connection->pair; pair->name = mpd_parser_get_name(connection->parser); pair->value = mpd_parser_get_value(connection->parser); connection->pair_state = PAIR_STATE_FLOATING; return pair; } /* unreachable */ assert(false); return NULL; } struct mpd_pair * mpd_recv_pair_named(struct mpd_connection *connection, const char *name) { struct mpd_pair *pair; while ((pair = mpd_recv_pair(connection)) != NULL) { if (strcmp(pair->name, name) == 0) return pair; mpd_return_pair(connection, pair); } return NULL; } void mpd_return_pair(struct mpd_connection *connection, mpd_unused struct mpd_pair *pair) { assert(connection != NULL); assert(pair != NULL); assert(connection->pair_state == PAIR_STATE_FLOATING); assert(pair == &connection->pair); connection->pair_state = PAIR_STATE_NONE; } void mpd_enqueue_pair(struct mpd_connection *connection, struct mpd_pair *pair) { assert(connection != NULL); if (pair != NULL) { /* enqueue the pair which was returned by mpd_recv_pair() */ assert(connection->pair_state == PAIR_STATE_FLOATING); assert(pair == &connection->pair); assert(pair->name != NULL && pair->value != NULL); connection->pair_state = PAIR_STATE_QUEUED; } else { /* enqueue the NULL pair */ assert(connection->pair_state == PAIR_STATE_NONE); connection->pair_state = PAIR_STATE_NULL; } } MusicPlayerDaemon-libmpdclient-5073329/src/replay_gain.c000066400000000000000000000043401505242054600231660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include "run.h" #include #include enum mpd_replay_gain_mode mpd_parse_replay_gain_name(const char *name) { if (strcmp(name, "off") == 0) return MPD_REPLAY_OFF; else if (strcmp(name, "track") == 0) return MPD_REPLAY_TRACK; else if (strcmp(name, "album") == 0) return MPD_REPLAY_ALBUM; else if (strcmp(name, "auto") == 0) return MPD_REPLAY_AUTO; else return MPD_REPLAY_UNKNOWN; } bool mpd_send_replay_gain_status(struct mpd_connection *connection) { return mpd_send_command(connection, "replay_gain_status", NULL); } const char * mpd_lookup_replay_gain_mode(enum mpd_replay_gain_mode mode) { switch (mode) { case MPD_REPLAY_OFF: return "off"; case MPD_REPLAY_TRACK: return "track"; case MPD_REPLAY_ALBUM: return "album"; case MPD_REPLAY_AUTO: return "auto"; case MPD_REPLAY_UNKNOWN: return NULL; } return NULL; } enum mpd_replay_gain_mode mpd_recv_replay_gain_status(struct mpd_connection *connection) { enum mpd_replay_gain_mode mode; struct mpd_pair *pair; pair = mpd_recv_pair_named(connection, "replay_gain_mode"); if (pair != NULL) { mode = mpd_parse_replay_gain_name(pair->value); mpd_return_pair(connection, pair); } else mode = MPD_REPLAY_UNKNOWN; return mode; } enum mpd_replay_gain_mode mpd_run_replay_gain_status(struct mpd_connection *connection) { enum mpd_replay_gain_mode mode; if (!mpd_run_check(connection) || !mpd_send_replay_gain_status(connection)) return MPD_REPLAY_UNKNOWN; mode = mpd_recv_replay_gain_status(connection); if (!mpd_response_finish(connection)) return MPD_REPLAY_UNKNOWN; return mode; } bool mpd_send_replay_gain_mode(struct mpd_connection *connection, enum mpd_replay_gain_mode mode) { return mpd_send_command(connection, "replay_gain_mode", mpd_lookup_replay_gain_mode(mode), NULL); } bool mpd_run_replay_gain_mode(struct mpd_connection *connection, enum mpd_replay_gain_mode mode) { return mpd_run_check(connection) && mpd_send_replay_gain_mode(connection, mode) && mpd_response_finish(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/request.c000066400000000000000000000065521505242054600223730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include "request.h" #include #include "internal.h" #include #include #include #include #include char * mpd_sanitize_arg(const char *src) { assert(src != NULL); /* instead of counting in that loop above, just * use a bit more memory and half running time */ char *result = malloc(strlen(src) * 2 + 1); if (result == NULL) return NULL; char *dest = result; char ch; do { ch = *src++; if (ch == '"' || ch == '\\') *dest++ = '\\'; *dest++ = ch; } while (ch != 0); return result; } bool mpd_request_begin(struct mpd_connection *connection) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return false; if (connection->request) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "search already in progress"); return false; } return true; } bool mpd_request_command(struct mpd_connection *connection, const char *cmd) { connection->request = strdup(cmd); if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } return true; } char * mpd_request_prepare_append(struct mpd_connection *connection, size_t add_length) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return NULL; if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "no search in progress"); return NULL; } const size_t old_length = strlen(connection->request); char *new_request = realloc(connection->request, old_length + add_length + 1); if (new_request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return NULL; } connection->request = new_request; return new_request + old_length; } bool mpd_request_add_sort(struct mpd_connection *connection, const char *name, bool descending) { assert(connection != NULL); const size_t size = 64; char *dest = mpd_request_prepare_append(connection, size); if (dest == NULL) return false; snprintf(dest, size, " sort %s%s", descending ? "-" : "", name); return true; } bool mpd_request_add_window(struct mpd_connection *connection, unsigned start, unsigned end) { assert(connection != NULL); assert(start <= end); const size_t size = 64; char *dest = mpd_request_prepare_append(connection, size); if (dest == NULL) return false; if (end == UINT_MAX) /* the special value -1 means "open end" */ snprintf(dest, size, " window %u:", start); else snprintf(dest, size, " window %u:%u", start, end); return true; } bool mpd_request_commit(struct mpd_connection *connection) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) { mpd_request_cancel(connection); return false; } if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "no search in progress"); return false; } bool success = mpd_send_command(connection, connection->request, NULL); free(connection->request); connection->request = NULL; return success; } void mpd_request_cancel(struct mpd_connection *connection) { assert(connection != NULL); free(connection->request); connection->request = NULL; } MusicPlayerDaemon-libmpdclient-5073329/src/request.h000066400000000000000000000014561505242054600223760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #ifndef MPD_ISEARCH_H #define MPD_ISEARCH_H #include #include struct mpd_connection; char * mpd_sanitize_arg(const char *src); bool mpd_request_begin(struct mpd_connection *connection); bool mpd_request_command(struct mpd_connection *connection, const char *cmd); char * mpd_request_prepare_append(struct mpd_connection *connection, size_t add_length); bool mpd_request_add_sort(struct mpd_connection *connection, const char *name, bool descending); bool mpd_request_add_window(struct mpd_connection *connection, unsigned start, unsigned end); bool mpd_request_commit(struct mpd_connection *connection); void mpd_request_cancel(struct mpd_connection *connection); #endif MusicPlayerDaemon-libmpdclient-5073329/src/resolver.c000066400000000000000000000074401505242054600225410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include "resolver.h" #include "config.h" #include #include #include #include #ifdef _WIN32 # include # include #else # include # include #ifdef ENABLE_TCP # include # include # include #endif #endif struct resolver { enum { TYPE_ZERO, TYPE_ONE, TYPE_ANY } type; #ifdef ENABLE_TCP #ifdef HAVE_GETADDRINFO struct addrinfo *ai; const struct addrinfo *next; #else struct sockaddr_in sin; #endif #endif struct resolver_address current; #ifndef _WIN32 struct sockaddr_un saun; #endif }; struct resolver * resolver_new(const char *host, unsigned port) { struct resolver *resolver; resolver = malloc(sizeof(*resolver)); if (resolver == NULL) return NULL; if (host[0] == '/' || host[0] == '@') { #ifndef _WIN32 const bool is_abstract = *host == '@'; /* sun_path must be null-terminated unless it's an abstract socket */ const size_t path_length = strlen(host) + !is_abstract; if (path_length > sizeof(resolver->saun.sun_path)) { free(resolver); return NULL; } resolver->saun.sun_family = AF_UNIX; memcpy(resolver->saun.sun_path, host, path_length); if (host[0] == '@') /* abstract socket */ resolver->saun.sun_path[0] = 0; resolver->current.family = PF_UNIX; resolver->current.protocol = 0; resolver->current.addrlen = sizeof(resolver->saun) - sizeof(resolver->saun.sun_path) + path_length; resolver->current.addr = (const struct sockaddr *)&resolver->saun; resolver->type = TYPE_ONE; #else /* _WIN32 */ /* there are no UNIX domain sockets on Windows */ free(resolver); return NULL; #endif /* _WIN32 */ } else { #ifdef ENABLE_TCP #ifdef HAVE_GETADDRINFO struct addrinfo hints; char service[20]; int ret; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(service, sizeof(service), "%d", port); ret = getaddrinfo(host, service, &hints, &resolver->ai); if (ret != 0) { free(resolver); return NULL; } resolver->next = resolver->ai; resolver->type = TYPE_ANY; #else const struct hostent *he; he = gethostbyname(host); if (he == NULL) { free(resolver); return NULL; } if (he->h_addrtype != AF_INET) { free(resolver); return NULL; } memset(&resolver->sin, 0, sizeof(resolver->sin)); resolver->sin.sin_family = AF_INET; resolver->sin.sin_port = htons(port); memcpy((char *)&resolver->sin.sin_addr.s_addr, (char *)he->h_addr, he->h_length); resolver->current.family = PF_INET; resolver->current.protocol = 0; resolver->current.addrlen = sizeof(resolver->sin); resolver->current.addr = (const struct sockaddr *)&resolver->sin; resolver->type = TYPE_ONE; #endif #else /* !ENABLE_TCP */ (void)port; free(resolver); return NULL; #endif } return resolver; } void resolver_free(struct resolver *resolver) { #if defined(ENABLE_TCP) && defined(HAVE_GETADDRINFO) if (resolver->type == TYPE_ANY) freeaddrinfo(resolver->ai); #endif free(resolver); } const struct resolver_address * resolver_next(struct resolver *resolver) { if (resolver->type == TYPE_ZERO) return NULL; if (resolver->type == TYPE_ONE) { resolver->type = TYPE_ZERO; return &resolver->current; } #if defined(ENABLE_TCP) && defined(HAVE_GETADDRINFO) if (resolver->next == NULL) return NULL; resolver->current.family = resolver->next->ai_family; resolver->current.protocol = resolver->next->ai_protocol; resolver->current.addrlen = resolver->next->ai_addrlen; resolver->current.addr = resolver->next->ai_addr; resolver->next = resolver->next->ai_next; return &resolver->current; #else return NULL; #endif } MusicPlayerDaemon-libmpdclient-5073329/src/resolver.h000066400000000000000000000007541505242054600225470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef LIBMPDCLIENT_RESOLVER_H #define LIBMPDCLIENT_RESOLVER_H #include struct resolver; struct resolver_address { int family; int protocol; size_t addrlen; const struct sockaddr *addr; }; struct resolver * resolver_new(const char *host, unsigned port); void resolver_free(struct resolver *resolver); const struct resolver_address * resolver_next(struct resolver *resolver); #endif MusicPlayerDaemon-libmpdclient-5073329/src/response.c000066400000000000000000000037541505242054600225420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include "internal.h" #include bool mpd_response_finish(struct mpd_connection *connection) { struct mpd_pair *pair; if (mpd_error_is_defined(&connection->error)) return false; if (connection->pair_state == PAIR_STATE_NULL) /* reset the stored NULL pair because it will conflict with an assertion within the loop */ connection->pair_state = PAIR_STATE_NONE; while (connection->receiving) { assert(!mpd_error_is_defined(&connection->error)); connection->discrete_finished = false; pair = mpd_recv_pair(connection); assert(pair != NULL || !connection->receiving || (connection->sending_command_list && connection->discrete_finished) || mpd_error_is_defined(&connection->error)); if (pair != NULL) mpd_return_pair(connection, pair); } return !mpd_error_is_defined(&connection->error); } bool mpd_response_next(struct mpd_connection *connection) { struct mpd_pair *pair; if (mpd_error_is_defined(&connection->error)) return false; if (!connection->receiving) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "Response is already finished"); return false; } if (!connection->sending_command_list_ok) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "Not in command list mode"); return false; } while (!connection->discrete_finished) { if (connection->command_list_remaining == 0 || !connection->receiving) { mpd_error_code(&connection->error, MPD_ERROR_MALFORMED); mpd_error_message(&connection->error, "No list_OK found"); return false; } pair = mpd_recv_pair(connection); if (pair != NULL) mpd_return_pair(connection, pair); else if (mpd_error_is_defined(&connection->error)) return false; } connection->discrete_finished = false; return true; } MusicPlayerDaemon-libmpdclient-5073329/src/rplaylist.c000066400000000000000000000016511505242054600227210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include "internal.h" #include struct mpd_playlist * mpd_recv_playlist(struct mpd_connection *connection) { struct mpd_pair *pair; struct mpd_playlist *playlist; pair = mpd_recv_pair_named(connection, "playlist"); if (pair == NULL) return NULL; playlist = mpd_playlist_begin(pair); mpd_return_pair(connection, pair); if (playlist == NULL) { mpd_error_entity(&connection->error); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_playlist_feed(playlist, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { assert(pair == NULL); mpd_playlist_free(playlist); return NULL; } /* unread this pair for the next mpd_recv_playlist() call */ mpd_enqueue_pair(connection, pair); return playlist; } MusicPlayerDaemon-libmpdclient-5073329/src/run.c000066400000000000000000000011361505242054600215000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "run.h" #include #include #include "internal.h" /** * Checks whether it is possible to run a command now. */ bool mpd_run_check(struct mpd_connection *connection) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return false; if (connection->sending_command_list) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "Not possible in command list mode"); return false; } return true; } MusicPlayerDaemon-libmpdclient-5073329/src/run.h000066400000000000000000000007311505242054600215050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_RUN_H #define MPD_RUN_H #include struct mpd_connection; /** * Check if it's possible to run a single command via mpd_run_X(). * This is not possible if the connection is currently sending a * command list. * * @return true if that's possible, and false if not (error set * accordingly) */ bool mpd_run_check(struct mpd_connection *connection); #endif MusicPlayerDaemon-libmpdclient-5073329/src/search.c000066400000000000000000000166041505242054600221470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include "request.h" #include "iso8601.h" #include #include #include #include #include bool mpd_search_db_songs(struct mpd_connection *connection, bool exact) { return mpd_request_begin(connection) && mpd_request_command(connection, exact ? "find" : "search"); } bool mpd_search_add_db_songs(struct mpd_connection *connection, bool exact) { return mpd_request_begin(connection) && mpd_request_command(connection, exact ? "findadd" : "searchadd"); } bool mpd_search_queue_songs(struct mpd_connection *connection, bool exact) { return mpd_request_begin(connection) && mpd_request_command(connection, exact ? "playlistfind" : "playlistsearch"); } bool mpd_search_db_tags(struct mpd_connection *connection, enum mpd_tag_type type) { assert(connection != NULL); if (!mpd_request_begin(connection)) return false; const char *strtype = mpd_tag_name(type); if (strtype == NULL) { mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); mpd_error_message(&connection->error, "invalid type specified"); return false; } const size_t len = 5 + strlen(strtype) + 1; connection->request = malloc(len); if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } snprintf(connection->request, len, "list %s", strtype); return true; } bool mpd_count_db_songs(struct mpd_connection *connection) { assert(connection != NULL); return mpd_request_begin(connection) && mpd_request_command(connection, "count"); } bool mpd_searchcount_db_songs(struct mpd_connection *connection) { assert(connection != NULL); return mpd_request_begin(connection) && mpd_request_command(connection, "searchcount"); } static bool mpd_search_add_constraint(struct mpd_connection *connection, mpd_unused enum mpd_operator oper, const char *name, const char *value) { assert(connection != NULL); assert(name != NULL); assert(value != NULL); char *arg = mpd_sanitize_arg(value); if (arg == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } const size_t add_length = 1 + strlen(name) + 2 + strlen(arg) + 1; char *dest = mpd_request_prepare_append(connection, add_length); if (dest == NULL) { free(arg); return false; } sprintf(dest, " %s \"%s\"", name, arg); free(arg); return true; } bool mpd_search_add_base_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value) { return mpd_search_add_constraint(connection, oper, "base", value); } bool mpd_search_add_uri_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value) { return mpd_search_add_constraint(connection, oper, "file", value); } bool mpd_search_add_tag_constraint(struct mpd_connection *connection, enum mpd_operator oper, enum mpd_tag_type type, const char *value) { assert(connection != NULL); assert(value != NULL); const char *strtype = mpd_tag_name(type); if (strtype == NULL) { mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); mpd_error_message(&connection->error, "invalid type specified"); return false; } return mpd_search_add_constraint(connection, oper, strtype, value); } bool mpd_search_add_any_tag_constraint(struct mpd_connection *connection, enum mpd_operator oper, const char *value) { return mpd_search_add_constraint(connection, oper, "any", value); } bool mpd_search_add_modified_since_constraint(struct mpd_connection *connection, enum mpd_operator oper, time_t value) { char buffer[64]; if (!iso8601_datetime_format(buffer, sizeof(buffer), value)) { mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); mpd_error_message(&connection->error, "failed to format time stamp"); return false; } return mpd_search_add_constraint(connection, oper, "modified-since", buffer); } bool mpd_search_add_added_since_constraint(struct mpd_connection *connection, enum mpd_operator oper, time_t value) { char buffer[64]; if (!iso8601_datetime_format(buffer, sizeof(buffer), value)) { mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT); mpd_error_message(&connection->error, "failed to format time stamp"); return false; } return mpd_search_add_constraint(connection, oper, "added-since", buffer); } bool mpd_search_add_expression(struct mpd_connection *connection, const char *expression) { assert(connection != NULL); assert(expression != NULL); char *arg = mpd_sanitize_arg(expression); if (arg == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } const size_t add_length = 2 + strlen(arg) + 1; char *dest = mpd_request_prepare_append(connection, add_length); if (dest == NULL) { free(arg); return false; } sprintf(dest, " \"%s\"", arg); free(arg); return true; } bool mpd_search_add_group_tag(struct mpd_connection *connection, enum mpd_tag_type type) { assert(connection != NULL); const size_t size = 64; char *dest = mpd_request_prepare_append(connection, size); if (dest == NULL) return false; snprintf(dest, size, " group %s", mpd_tag_name(type)); return true; } bool mpd_search_add_sort_name(struct mpd_connection *connection, const char *name, bool descending) { return mpd_request_add_sort(connection, name, descending); } bool mpd_search_add_sort_tag(struct mpd_connection *connection, enum mpd_tag_type type, bool descending) { return mpd_search_add_sort_name(connection, mpd_tag_name(type), descending); } bool mpd_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_request_add_window(connection, start, end); } bool mpd_search_add_position(struct mpd_connection *connection, unsigned position, enum mpd_position_whence whence) { assert(connection != NULL); const size_t size = 64; char *dest = mpd_request_prepare_append(connection, size); if (dest == NULL) return false; const char *whence_s = mpd_position_whence_char(whence); snprintf(dest, size, " position %s%u", whence_s, position); return true; } bool mpd_search_commit(struct mpd_connection *connection) { return mpd_request_commit(connection); } void mpd_search_cancel(struct mpd_connection *connection) { mpd_request_cancel(connection); } struct mpd_pair * mpd_recv_pair_tag(struct mpd_connection *connection, enum mpd_tag_type type) { assert(connection != NULL); const char *name = mpd_tag_name(type); if (name == NULL) return NULL; return mpd_recv_pair_named(connection, name); } bool mpd_search_add_db_songs_to_playlist(struct mpd_connection *connection, const char *playlist_name) { assert(connection != NULL); assert(playlist_name != NULL); if (!mpd_request_begin(connection)) return false; char *arg = mpd_sanitize_arg(playlist_name); if (arg == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } const size_t len = 13 + strlen(arg) + 2; connection->request = malloc(len); if (connection->request == NULL) { free(arg); mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } snprintf(connection->request, len, "searchaddpl \"%s\" ", arg); free(arg); return true; } MusicPlayerDaemon-libmpdclient-5073329/src/send.c000066400000000000000000000263251505242054600216340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include "isend.h" #include "internal.h" #include "sync.h" #include "config.h" // for HAVE_USELOCALE #include #include #include #ifdef HAVE_USELOCALE #include #endif /* (bits+1)/3 (plus the sign character) */ enum { INTLEN = (sizeof(int) * CHAR_BIT + 1) / 3 + 1, LONGLONGLEN = (sizeof(long long) * CHAR_BIT + 1) / 3 + 1, FLOATLEN = LONGLONGLEN + 8, }; static void format_range(char *buffer, size_t size, unsigned start, unsigned end) { if (end == UINT_MAX) /* the special value -1 means "open end" */ snprintf(buffer, size, "%u:", start); else snprintf(buffer, size, "%u:%u", start, end); } static void format_frange(char *buffer, size_t size, float start, float end) { #ifdef HAVE_USELOCALE // use the POSIX locale to format floating point numbers const locale_t my_locale = newlocale(LC_NUMERIC_MASK, "C", NULL); const locale_t old_locale = uselocale(my_locale); #endif /* the special value 0.0 means "open range" */ if (end >= 0) snprintf(buffer, size, "%1.3f:%1.3f", (double)start, (double)end); else snprintf(buffer, size, "%1.3f:", (double)start); #ifdef HAVE_USELOCALE uselocale(old_locale); freelocale(my_locale); #endif } /** * Checks whether it is possible to send a command now. */ static bool send_check(struct mpd_connection *connection) { assert(connection != NULL); if (mpd_error_is_defined(&connection->error)) return false; if (connection->receiving) { mpd_error_code(&connection->error, MPD_ERROR_STATE); mpd_error_message(&connection->error, "Cannot send a new command while " "receiving another response"); return false; } return true; } bool mpd_send_command(struct mpd_connection *connection, const char *command, ...) { va_list ap; bool success; if (!send_check(connection)) return false; va_start(ap, command); success = mpd_sync_send_command_v(connection->async, mpd_connection_timeout(connection), command, ap); va_end(ap); if (!success) { mpd_connection_sync_error(connection); return false; } if (!connection->sending_command_list) { /* the caller might expect that we have flushed the output buffer when this function returns */ if (!mpd_flush(connection)) return false; connection->receiving = true; } else if (connection->sending_command_list_ok) ++connection->command_list_remaining; return true; } bool mpd_send_command2(struct mpd_connection *connection, const char *command) { bool success; if (!send_check(connection)) return false; success = mpd_sync_send_command(connection->async, mpd_connection_timeout(connection), command, NULL); if (!success) { mpd_connection_sync_error(connection); return false; } return true; } bool mpd_send_int_command(struct mpd_connection *connection, const char *command, int arg) { char arg_string[INTLEN]; snprintf(arg_string, sizeof(arg_string), "%i", arg); return mpd_send_command(connection, command, arg_string, NULL); } bool mpd_send_int2_command(struct mpd_connection *connection, const char *command, int arg1, int arg2) { char arg1_string[INTLEN], arg2_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%i", arg1); snprintf(arg2_string, sizeof(arg2_string), "%i", arg2); return mpd_send_command(connection, command, arg1_string, arg2_string, NULL); } bool mpd_send_int3_command(struct mpd_connection *connection, const char *command, int arg1, int arg2, int arg3) { char arg1_string[INTLEN], arg2_string[INTLEN], arg3_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%i", arg1); snprintf(arg2_string, sizeof(arg2_string), "%i", arg2); snprintf(arg3_string, sizeof(arg3_string), "%i", arg3); return mpd_send_command(connection, command, arg1_string, arg2_string, arg3_string, NULL); } bool mpd_send_float_command(struct mpd_connection *connection, const char *command, float arg) { #ifdef HAVE_USELOCALE // use the POSIX locale to format floating point numbers const locale_t my_locale = newlocale(LC_NUMERIC_MASK, "C", NULL); const locale_t old_locale = uselocale(my_locale); #endif char arg_string[FLOATLEN]; snprintf(arg_string, sizeof(arg_string), "%f", (double)arg); #ifdef HAVE_USELOCALE uselocale(old_locale); freelocale(my_locale); #endif return mpd_send_command(connection, command, arg_string, NULL); } bool mpd_send_u_command(struct mpd_connection *connection, const char *command, unsigned arg1) { char arg1_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%u", arg1); return mpd_send_command(connection, command, arg1_string, NULL); } bool mpd_send_u2_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned arg2) { char arg1_string[INTLEN]; char arg2_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%u", arg1); snprintf(arg2_string, sizeof(arg2_string), "%u", arg2); return mpd_send_command(connection, command, arg1_string, arg2_string,NULL); } bool mpd_send_u_f_command(struct mpd_connection *connection, const char *command, unsigned arg1, float arg2) { #ifdef HAVE_USELOCALE // use the POSIX locale to format floating point numbers const locale_t my_locale = newlocale(LC_NUMERIC_MASK, "C", NULL); const locale_t old_locale = uselocale(my_locale); #endif char arg1_string[INTLEN], arg2_string[FLOATLEN]; snprintf(arg1_string, sizeof(arg1_string), "%u", arg1); snprintf(arg2_string, sizeof(arg2_string), "%.3f", (double)arg2); #ifdef HAVE_USELOCALE uselocale(old_locale); freelocale(my_locale); #endif return mpd_send_command(connection, command, arg1_string, arg2_string, NULL); } bool mpd_send_u_s_command(struct mpd_connection *connection, const char *command, unsigned arg1, const char *arg2) { char arg1_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%i", arg1); return mpd_send_command(connection, command, arg1_string, arg2, NULL); } bool mpd_send_u_s_s_command(struct mpd_connection *connection, const char *command, unsigned arg1, const char *arg2, const char *arg3) { char arg1_string[INTLEN]; snprintf(arg1_string, sizeof(arg1_string), "%i", arg1); return mpd_send_command(connection, command, arg1_string, arg2, arg3, NULL); } bool mpd_send_s_s_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2) { return mpd_send_command(connection, command, arg1, arg2, NULL); } bool mpd_send_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned arg2) { char arg2_string[INTLEN]; snprintf(arg2_string, sizeof(arg2_string), "%u", arg2); return mpd_send_command(connection, command, arg1, arg2_string, NULL); } bool mpd_send_s_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2, unsigned arg3) { char arg3_string[INTLEN]; snprintf(arg3_string, sizeof(arg3_string), "%u", arg3); return mpd_send_command(connection, command, arg1, arg2, arg3_string, NULL); } bool mpd_send_s_s_s_s_u_command(struct mpd_connection *connection, const char *command, const char *arg1, const char *arg2, const char *arg3, const char *arg4, unsigned arg5) { char arg5_string[INTLEN]; snprintf(arg5_string, sizeof(arg5_string), "%u", arg5); return mpd_send_command(connection, command, arg1, arg2, arg3, arg4, arg5_string, NULL); } bool mpd_send_range_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned arg2) { char arg_string[INTLEN*2+1]; format_range(arg_string, sizeof(arg_string), arg1, arg2); return mpd_send_command(connection, command, arg_string, NULL); } bool mpd_send_s_range_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end) { char range_string[INTLEN * 2 + 1]; format_range(range_string, sizeof(range_string), start, end); return mpd_send_command(connection, command, arg1, range_string, NULL); } bool mpd_send_s_range_to_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end, char *to) { char range_string[INTLEN * 2 + 1]; format_range(range_string, sizeof(range_string), start, end); return mpd_send_command(connection, command, arg1, range_string, to, NULL); } bool mpd_send_s_range_to_u_command(struct mpd_connection *connection, const char *command, const char *arg1, unsigned start, unsigned end, unsigned to) { char arg2_string[INTLEN * 2 + 1], arg3_string[INTLEN + 1]; format_range(arg2_string, sizeof(arg2_string), start, end); snprintf(arg3_string, sizeof(arg3_string), "%u", to); return mpd_send_command(connection, command, arg1, arg2_string, arg3_string, NULL); } bool mpd_send_i_range_command(struct mpd_connection *connection, const char *command, int arg1, unsigned start, unsigned end) { char arg1_string[INTLEN + 1], arg2_string[INTLEN * 2 + 1]; snprintf(arg1_string, sizeof(arg1_string), "%i", arg1); format_range(arg2_string, sizeof(arg2_string), start, end); return mpd_send_command(connection, command, arg1_string, arg2_string, NULL); } bool mpd_send_u_range_command(struct mpd_connection *connection, const char *command, unsigned arg1, unsigned start, unsigned end) { char arg1_string[INTLEN + 1], arg2_string[INTLEN * 2 + 1]; snprintf(arg1_string, sizeof(arg1_string), "%u", arg1); format_range(arg2_string, sizeof(arg2_string), start, end); return mpd_send_command(connection, command, arg1_string, arg2_string, NULL); } bool mpd_send_range_u_command(struct mpd_connection *connection, const char *command, unsigned start, unsigned end, unsigned arg2) { char arg1_string[INTLEN*2+1], arg2_string[INTLEN]; format_range(arg1_string, sizeof(arg1_string), start, end); snprintf(arg2_string, sizeof(arg2_string), "%i", arg2); return mpd_send_command(connection, command, arg1_string, arg2_string, NULL); } bool mpd_send_range_to_command(struct mpd_connection *connection, const char *command, unsigned start, unsigned end, const char *to) { char arg1_string[INTLEN*2+1]; format_range(arg1_string, sizeof(arg1_string), start, end); return mpd_send_command(connection, command, arg1_string, to, NULL); } bool mpd_send_u_frange_command(struct mpd_connection *connection, const char *command, unsigned arg1, float start, float end) { /* : */ char arg1_string[INTLEN + 1]; char range_string[FLOATLEN * 2 + 1 + 1]; snprintf(arg1_string, sizeof(arg1_string), "%u", arg1); format_frange(range_string, sizeof(range_string), start, end); return mpd_send_command(connection, command, arg1_string, range_string, NULL); } bool mpd_send_ll_command(struct mpd_connection *connection, const char *command, long long arg) { char arg_string[LONGLONGLEN]; #ifdef _WIN32 snprintf(arg_string, sizeof(arg_string), "%ld", (long)arg); #else snprintf(arg_string, sizeof(arg_string), "%lld", arg); #endif return mpd_send_command(connection, command, arg_string, NULL); } bool mpd_flush(struct mpd_connection *connection) { if (!mpd_sync_flush(connection->async, mpd_connection_timeout(connection))) { mpd_connection_sync_error(connection); return false; } return true; } MusicPlayerDaemon-libmpdclient-5073329/src/settings.c000066400000000000000000000137261505242054600225440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include "config.h" #include "internal.h" #include #include #include /** * This opaque object represents the connection settings used to * connect to a MPD server. * Call mpd_settings_new() to create a new instance. */ struct mpd_settings { /** * The hostname, in null-terminated string form. * Can also be a local socket path on UNIX systems. * Should never be null after mpd_settings_new(). */ char *host; /** * The port number, as an unsigned integer. * Will be 0 if the host field is a local socket path. */ unsigned port; /** * The timeout in milliseconds, as an unsigned integer. Never zero. */ unsigned timeout_ms; /** * The password used to connect to a MPD server, may be null. */ char *password; /** * A pointer to the next alternative set of settings to try, if any. * Null indicates there are no (more) alternatives to try. */ struct mpd_settings *next; }; /** * Parses the password from the host specification in the form * "password@hostname". * * @param settings a settings object. both settings->host and * settings->password may be modified by this function * @return true on success, false on out of memory * */ static bool mpd_parse_host_password(struct mpd_settings *settings) { char *at, *oldhost; size_t host_len, at_pos; assert(settings->password == NULL); if (settings->host == NULL || /* if the MPD_HOST begins with a '@' then it's not an empty password but an abstract socket */ *settings->host == '@') return true; at = strchr(settings->host, '@'); if (at == NULL) return true; at_pos = at - settings->host; settings->password = malloc(at_pos + 1); if (settings->password == NULL) return false; memcpy(settings->password, settings->host, at_pos); (settings->password)[at_pos] = 0; /* reallocate host, otherwise free() would not work properly */ host_len = strlen(settings->host) - at_pos; oldhost = settings->host; settings->host = malloc(host_len); if (settings->host == NULL) { settings->host = oldhost; return false; } memcpy(settings->host, &oldhost[at_pos + 1], host_len - 1); settings->host[host_len - 1] = 0; free(oldhost); return true; } /** * Parses the host specification. If not specified, it attempts to * load it from the environment variable MPD_HOST. * * @param settings a settings object. both settings->host and * settings->password may be modified by this function * @return true on success, false on out of memory */ static bool mpd_check_host(struct mpd_settings *settings) { const char *host_getenv = getenv("MPD_HOST"); assert(settings->password == NULL); if (settings->host == NULL && host_getenv != NULL) { /* getent should not be freed (mpd_settings_free()); hence we * allocate a new string */ settings->host = strdup(host_getenv); if (settings->host == NULL) return false; } if (settings->host != NULL) { if (!mpd_parse_host_password(settings)) return false; } return true; } /** * Parses the port specification. If not specified (0), it attempts * to load it from the environment variable MPD_PORT. */ static unsigned mpd_check_port(unsigned port) { if (port == 0) { const char *env_port = getenv("MPD_PORT"); if (env_port != NULL) port = strtoul(env_port, NULL, 10); } return port; } static unsigned mpd_default_timeout_ms(void) { const char *timeout_string = getenv("MPD_TIMEOUT"); if (timeout_string != NULL) { const unsigned timeout_s = strtoul(timeout_string, NULL, 10); if (timeout_s > 0) return timeout_s * 1000; } /* 30s is the default */ return 30000; } struct mpd_settings * mpd_settings_new(const char *host, unsigned port, unsigned timeout_ms, const char *reserved, const char *password) { (void)reserved; struct mpd_settings *settings = malloc(sizeof(*settings)); if (settings == NULL) return settings; settings->next = NULL; if (host != NULL) { settings->host = strdup(host); if (settings->host == NULL) { free(settings); return NULL; } } else settings->host = NULL; settings->password = NULL; port = mpd_check_port(port); if (!mpd_check_host(settings)) { mpd_settings_free(settings); return NULL; } if (settings->password == NULL && password != NULL) { settings->password = strdup(password); if (settings->password == NULL) { free(settings->host); free(settings); return NULL; } } if (settings->host == NULL) { #ifdef DEFAULT_SOCKET if (port == 0) { /* default to local socket only if no port was explicitly configured */ #ifdef ENABLE_TCP settings->next = mpd_settings_new(DEFAULT_HOST, DEFAULT_PORT, timeout_ms, reserved, password); if (settings->next == NULL) { mpd_settings_free(settings); return NULL; } #endif settings->host = strdup(DEFAULT_SOCKET); } else #endif settings->host = strdup(DEFAULT_HOST); if (settings->host == NULL) { free(settings->password); free(settings); return NULL; } } settings->timeout_ms = timeout_ms != 0 ? timeout_ms : mpd_default_timeout_ms(); settings->port = settings->host[0] == '/' || settings->host[0] == '@' ? 0 /* no port for local socket */ : (port != 0 ? port : DEFAULT_PORT); return settings; } void mpd_settings_free(struct mpd_settings *settings) { if (settings->next != NULL) mpd_settings_free(settings->next); free(settings->host); free(settings->password); free(settings); } const char * mpd_settings_get_host(const struct mpd_settings *settings) { return settings->host; } unsigned mpd_settings_get_port(const struct mpd_settings *settings) { return settings->port; } unsigned mpd_settings_get_timeout_ms(const struct mpd_settings *settings) { return settings->timeout_ms; } const char * mpd_settings_get_password(const struct mpd_settings *settings) { return settings->password; } const struct mpd_settings * mpd_settings_get_next(const struct mpd_settings *settings) { return settings->next; } MusicPlayerDaemon-libmpdclient-5073329/src/socket.c000066400000000000000000000070001505242054600221600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "socket.h" #include "fd_util.h" #include "resolver.h" #include "ierror.h" #include #include #include #include #ifdef _WIN32 # include # include #else # include # include # include # include # include # include # include # include #endif #ifndef MSG_DONTWAIT # define MSG_DONTWAIT 0 #endif #ifdef _WIN32 bool mpd_socket_global_init(struct mpd_error_info *error) { WSADATA wsaData; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 || LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) { mpd_error_system(error, 0); mpd_error_message(error, "Could not find usable WinSock DLL"); return false; } return true; } #endif /** * Wait for the socket to become writable. */ static int mpd_socket_wait_writable(int fd, struct timeval *tv) { fd_set fds; int ret; while (1) { FD_ZERO(&fds); FD_SET(fd, &fds); ret = select(fd + 1, NULL, &fds, NULL, tv); if (ret > 0) return 0; if (ret == 0 || !mpd_socket_ignore_errno(mpd_socket_errno())) return -1; } } /** * Wait until the socket is connected and check its result. Returns 1 * on success, 0 on timeout, -errno on error. */ static int mpd_socket_wait_connected(mpd_socket_t fd, struct timeval *tv) { int ret; int s_err = 0; socklen_t s_err_size = sizeof(s_err); ret = mpd_socket_wait_writable(fd, tv); if (ret < 0) return 0; ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&s_err, &s_err_size); if (ret < 0) return -mpd_socket_errno(); if (s_err != 0) return -s_err; return 1; } mpd_socket_t mpd_socket_connect(const char *host, unsigned port, const struct timeval *tv0, struct mpd_error_info *error) { struct timeval tv = *tv0; struct resolver *resolver; const struct resolver_address *address; int ret; resolver = resolver_new(host, port); if (resolver == NULL) { mpd_error_code(error, MPD_ERROR_RESOLVER); mpd_error_message(error, "Failed to resolve host name"); return -1; } assert(!mpd_error_is_defined(error)); while ((address = resolver_next(resolver)) != NULL) { mpd_socket_t fd = socket_cloexec_nonblock(address->family, SOCK_STREAM, address->protocol); if (fd == MPD_INVALID_SOCKET) { mpd_error_clear(error); mpd_error_errno(error); continue; } ret = connect(fd, address->addr, address->addrlen); if (ret == 0) { resolver_free(resolver); mpd_error_clear(error); return fd; } if (!mpd_socket_ignore_errno(mpd_socket_errno())) { mpd_error_clear(error); mpd_error_errno(error); mpd_socket_close(fd); continue; } ret = mpd_socket_wait_connected(fd, &tv); if (ret > 0) { resolver_free(resolver); mpd_error_clear(error); return fd; } if (ret == 0) { mpd_error_clear(error); mpd_error_code(error, MPD_ERROR_TIMEOUT); mpd_error_message(error, "Timeout while connecting"); } else if (ret < 0) { mpd_error_clear(error); mpd_error_system_message(error, -ret); } mpd_socket_close(fd); } resolver_free(resolver); return -1; } int mpd_socket_close(mpd_socket_t fd) { #ifndef _WIN32 return close(fd); #else return closesocket(fd); #endif } int mpd_socket_keepalive(mpd_socket_t fd, bool keepalive) { int keepalive_i = keepalive; return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *) &keepalive_i, sizeof keepalive_i); } MusicPlayerDaemon-libmpdclient-5073329/src/socket.h000066400000000000000000000025401505242054600221710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_SOCKET_H #define MPD_SOCKET_H #include #include #ifdef _WIN32 # include #else # include #endif struct timeval; struct mpd_error_info; #ifdef _WIN32 bool mpd_socket_global_init(struct mpd_error_info *error); #else static inline bool mpd_socket_global_init(struct mpd_error_info *error) { (void)error; return true; } #endif static inline int mpd_socket_errno(void) { #ifdef _WIN32 return WSAGetLastError(); #else return errno; #endif } /** * Can this error code be ignored? */ static inline bool mpd_socket_ignore_errno(int e) { #ifdef _WIN32 return e == WSAEINTR || e == WSAEINPROGRESS || e == WSAEWOULDBLOCK; #else return e == EINTR || e == EINPROGRESS || e == EAGAIN; #endif } /** * Connects the socket to the specified host and port. * * @return the socket file descriptor, or -1 on failure */ mpd_socket_t mpd_socket_connect(const char *host, unsigned port, const struct timeval *tv, struct mpd_error_info *error); /** * Closes a socket descriptor. This is a wrapper for close() or * closesocket(), depending on the OS. */ int mpd_socket_close(mpd_socket_t fd); /** * Sets (or unsets) keepalive on a socket descriptor. */ int mpd_socket_keepalive(mpd_socket_t fd, bool keepalive); #endif MusicPlayerDaemon-libmpdclient-5073329/src/song.c000066400000000000000000000251031505242054600216420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include "internal.h" #include "iso8601.h" #include "uri.h" #include "iaf.h" #include #include #include #include struct mpd_tag_value { struct mpd_tag_value *next; char *value; }; struct mpd_song { char *uri; struct mpd_tag_value tags[MPD_TAG_COUNT]; /** * Duration of the song in seconds, or 0 for unknown. */ unsigned duration; /** * Duration of the song in milliseconds, or 0 for unknown. */ unsigned duration_ms; /** * Start of the virtual song within the physical file in * seconds. */ unsigned start; /** * End of the virtual song within the physical file in * seconds. Zero means that the physical song file is * played to the end. */ unsigned end; /** * The POSIX UTC time stamp of the last modification, or 0 if * that is unknown. */ time_t last_modified; /** * The POSIX UTC time stamp of database addition, or 0 if * that is unknown. */ time_t added; /** * The position of this song within the queue. */ unsigned pos; /** * The id of this song within the queue. */ unsigned id; /** * The priority of this song within the queue. */ unsigned prio; #ifndef NDEBUG /** * This flag is used in an assertion: when it is set, you must * not call mpd_song_feed() again. It is a safeguard for * buggy callers. */ bool finished; #endif /** * The audio format as reported by MPD's decoder plugin. */ struct mpd_audio_format audio_format; }; static struct mpd_song * mpd_song_new(const char *uri) { struct mpd_song *song; assert(uri != NULL); assert(mpd_verify_uri(uri)); song = malloc(sizeof(*song)); if (song == NULL) /* out of memory */ return NULL; song->uri = strdup(uri); if (song->uri == NULL) { free(song); return NULL; } for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) song->tags[i].value = NULL; song->duration = 0; song->duration_ms = 0; song->start = 0; song->end = 0; song->last_modified = 0; song->added = 0; song->pos = 0; song->id = 0; song->prio = 0; memset(&song->audio_format, 0, sizeof(song->audio_format)); #ifndef NDEBUG song->finished = false; #endif return song; } void mpd_song_free(struct mpd_song *song) { assert(song != NULL); free(song->uri); for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) { struct mpd_tag_value *tag = &song->tags[i], *next; if (tag->value == NULL) continue; free(tag->value); tag = tag->next; while (tag != NULL) { assert(tag->value != NULL); free(tag->value); next = tag->next; free(tag); tag = next; } } free(song); } static bool mpd_song_add_tag(struct mpd_song *song, enum mpd_tag_type type, const char *value); struct mpd_song * mpd_song_dup(const struct mpd_song *song) { struct mpd_song *ret; bool success; assert(song != NULL); ret = mpd_song_new(song->uri); if (ret == NULL) /* out of memory */ return NULL; for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) { const struct mpd_tag_value *src_tag = &song->tags[i]; if (src_tag->value == NULL) continue; do { success = mpd_song_add_tag(ret, (enum mpd_tag_type)i, src_tag->value); if (!success) { mpd_song_free(ret); return NULL; } src_tag = src_tag->next; } while (src_tag != NULL); } ret->duration = song->duration; ret->duration_ms = song->duration_ms; ret->start = song->start; ret->end = song->end; ret->last_modified = song->last_modified; ret->added = song->added; ret->pos = song->pos; ret->id = song->id; ret->prio = song->prio; #ifndef NDEBUG ret->finished = true; #endif return ret; } const char * mpd_song_get_uri(const struct mpd_song *song) { assert(song != NULL); return song->uri; } /** * Adds a tag value to the song. * * @return true on success, false if the tag is not supported or if no * memory could be allocated */ static bool mpd_song_add_tag(struct mpd_song *song, enum mpd_tag_type type, const char *value) { struct mpd_tag_value *tag = &song->tags[type], *prev; if ((int)type < 0 || type >= MPD_TAG_COUNT) return false; if (tag->value == NULL) { tag->next = NULL; tag->value = strdup(value); if (tag->value == NULL) return false; } else { while (tag->next != NULL) tag = tag->next; prev = tag; tag = malloc(sizeof(*tag)); if (tag == NULL) return false; tag->value = strdup(value); if (tag->value == NULL) { free(tag); return false; } tag->next = NULL; prev->next = tag; } return true; } #ifdef UNUSED_CODE /** * Removes all values of the specified tag. */ static void mpd_song_clear_tag(struct mpd_song *song, enum mpd_tag_type type) { struct mpd_tag_value *tag = &song->tags[type]; if ((unsigned)type >= MPD_TAG_COUNT) return; if (tag->value == NULL) /* this tag type is empty */ return; /* free and clear the first value */ free(tag->value); tag->value = NULL; /* free all other values; no need to clear the "next" pointer, because it is "undefined" as long as value==NULL */ while ((tag = tag->next) != NULL) free(tag->value); } #endif const char * mpd_song_get_tag(const struct mpd_song *song, enum mpd_tag_type type, unsigned idx) { const struct mpd_tag_value *tag = &song->tags[type]; if ((int)type < 0) return NULL; if (tag->value == NULL) return NULL; while (idx-- > 0) { tag = tag->next; if (tag == NULL) return NULL; } return tag->value; } static void mpd_song_set_duration(struct mpd_song *song, unsigned duration) { song->duration = duration; } unsigned mpd_song_get_duration(const struct mpd_song *song) { assert(song != NULL); return song->duration > 0 ? song->duration : (song->duration_ms + 500u) / 1000u; } static void mpd_song_set_duration_ms(struct mpd_song *song, unsigned duration_ms) { song->duration_ms = duration_ms; } unsigned mpd_song_get_duration_ms(const struct mpd_song *song) { assert(song != NULL); return song->duration_ms > 0 ? song->duration_ms : (song->duration * 1000u); } unsigned mpd_song_get_start(const struct mpd_song *song) { assert(song != NULL); return song->start; } unsigned mpd_song_get_end(const struct mpd_song *song) { assert(song != NULL); return song->end; } static void mpd_song_set_last_modified(struct mpd_song *song, time_t mtime) { song->last_modified = mtime; } time_t mpd_song_get_last_modified(const struct mpd_song *song) { assert(song != NULL); return song->last_modified; } static void mpd_song_set_added(struct mpd_song *song, time_t addtime) { song->added = addtime; } time_t mpd_song_get_added(const struct mpd_song *song) { assert(song != NULL); return song->added; } void mpd_song_set_pos(struct mpd_song *song, unsigned pos) { assert(song != NULL); song->pos = pos; } unsigned mpd_song_get_pos(const struct mpd_song *song) { assert(song != NULL); return song->pos; } static void mpd_song_set_id(struct mpd_song *song, unsigned id) { song->id = id; } unsigned mpd_song_get_id(const struct mpd_song *song) { assert(song != NULL); return song->id; } static void mpd_song_set_prio(struct mpd_song *song, unsigned prio) { song->prio = prio; } unsigned mpd_song_get_prio(const struct mpd_song *song) { assert(song != NULL); return song->prio; } const struct mpd_audio_format * mpd_song_get_audio_format(const struct mpd_song *song) { assert(song != NULL); return !mpd_audio_format_is_empty(&song->audio_format) ? &song->audio_format : NULL; } struct mpd_song * mpd_song_begin(const struct mpd_pair *pair) { assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "file") != 0 || !mpd_verify_uri(pair->value)) { errno = EINVAL; return NULL; } return mpd_song_new(pair->value); } static void mpd_song_parse_range(struct mpd_song *song, const char *value) { assert(song != NULL); assert(value != NULL); char *endptr; double start, end; if (*value == '-') { start = 0.0; end = strtod(value + 1, NULL); } else { start = strtod(value, &endptr); if (*endptr != '-') return; end = strtod(endptr + 1, NULL); } song->start = start > 0.0 ? (unsigned)start : 0; if (end > 0.0) { song->end = (unsigned)end; if (song->end == 0) /* round up, because the caller must sees that there's an upper limit */ song->end = 1; } else song->end = 0; } static void mpd_song_parse_audio_format(struct mpd_song *song, const char *value) { assert(song != NULL); assert(value != NULL); mpd_parse_audio_format(&song->audio_format, value); } bool mpd_song_feed(struct mpd_song *song, const struct mpd_pair *pair) { enum mpd_tag_type tag_type; assert(song != NULL); assert(!song->finished); assert(pair != NULL); assert(pair->name != NULL); assert(pair->value != NULL); if (strcmp(pair->name, "file") == 0) { #ifndef NDEBUG song->finished = true; #endif return false; } if (*pair->value == 0) return true; tag_type = mpd_tag_name_parse(pair->name); if (tag_type != MPD_TAG_UNKNOWN) { mpd_song_add_tag(song, tag_type, pair->value); return true; } if (strcmp(pair->name, "Time") == 0) mpd_song_set_duration(song, strtoul(pair->value, NULL, 10)); else if (strcmp(pair->name, "duration") == 0) mpd_song_set_duration_ms(song, 1000 * atof(pair->value)); else if (strcmp(pair->name, "Range") == 0) mpd_song_parse_range(song, pair->value); else if (strcmp(pair->name, "Last-Modified") == 0) mpd_song_set_last_modified(song, iso8601_datetime_parse(pair->value)); else if (strcmp(pair->name, "Added") == 0) mpd_song_set_added(song, iso8601_datetime_parse(pair->value)); else if (strcmp(pair->name, "Pos") == 0) mpd_song_set_pos(song, strtoul(pair->value, NULL, 10)); else if (strcmp(pair->name, "Id") == 0) mpd_song_set_id(song, strtoul(pair->value, NULL, 10)); else if (strcmp(pair->name, "Prio") == 0) mpd_song_set_prio(song, strtoul(pair->value, NULL, 10)); else if (strcmp(pair->name, "Format") == 0) mpd_song_parse_audio_format(song, pair->value); return true; } struct mpd_song * mpd_recv_song(struct mpd_connection *connection) { struct mpd_pair *pair; struct mpd_song *song; pair = mpd_recv_pair_named(connection, "file"); if (pair == NULL) return NULL; song = mpd_song_begin(pair); mpd_return_pair(connection, pair); if (song == NULL) { mpd_error_entity(&connection->error); return NULL; } while ((pair = mpd_recv_pair(connection)) != NULL && mpd_song_feed(song, pair)) mpd_return_pair(connection, pair); if (mpd_error_is_defined(&connection->error)) { mpd_song_free(song); return NULL; } /* unread this pair for the next mpd_recv_song() call */ mpd_enqueue_pair(connection, pair); return song; } MusicPlayerDaemon-libmpdclient-5073329/src/stats.c000066400000000000000000000050001505242054600220240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include struct mpd_stats { unsigned number_of_artists; unsigned number_of_albums; unsigned number_of_songs; unsigned long uptime; unsigned long db_update_time; unsigned long play_time; unsigned long db_play_time; }; struct mpd_stats * mpd_stats_begin(void) { struct mpd_stats *stats = malloc(sizeof(struct mpd_stats)); if (stats == NULL) return NULL; stats->number_of_artists = 0; stats->number_of_albums = 0; stats->number_of_songs = 0; stats->uptime = 0; stats->db_update_time = 0; stats->play_time = 0; stats->db_play_time = 0; return stats; } void mpd_stats_feed(struct mpd_stats *stats, const struct mpd_pair *pair) { if (strcmp(pair->name, "artists") == 0) stats->number_of_artists = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "albums") == 0) stats->number_of_albums = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "songs") == 0) stats->number_of_songs = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "uptime") == 0) stats->uptime = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "db_update") == 0) stats->db_update_time = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "playtime") == 0) stats->play_time = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "db_playtime") == 0) stats->db_play_time = strtoul(pair->value, NULL, 10); } void mpd_stats_free(struct mpd_stats * stats) { assert(stats != NULL); free(stats); } unsigned mpd_stats_get_number_of_artists(const struct mpd_stats * stats) { assert(stats != NULL); return stats->number_of_artists; } unsigned mpd_stats_get_number_of_albums(const struct mpd_stats * stats) { assert(stats != NULL); return stats->number_of_albums; } unsigned mpd_stats_get_number_of_songs(const struct mpd_stats * stats) { assert(stats != NULL); return stats->number_of_songs; } unsigned long mpd_stats_get_uptime(const struct mpd_stats * stats) { assert(stats != NULL); return stats->uptime; } unsigned long mpd_stats_get_db_update_time(const struct mpd_stats * stats) { assert(stats != NULL); return stats->db_update_time; } unsigned long mpd_stats_get_play_time(const struct mpd_stats * stats) { assert(stats != NULL); return stats->play_time; } unsigned long mpd_stats_get_db_play_time(const struct mpd_stats * stats) { assert(stats != NULL); return stats->db_play_time; } MusicPlayerDaemon-libmpdclient-5073329/src/status.c000066400000000000000000000250341505242054600222220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include "iaf.h" #include #include #include #include /** * Information about MPD's current status. */ struct mpd_status { /** 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */ int volume; /** Queue repeat mode enabled? */ bool repeat; /** Random mode enabled? */ bool random; /** Single song mode enabled? */ enum mpd_single_state single; /** Song consume mode enabled? */ enum mpd_consume_state consume; /** Number of songs in the queue */ unsigned queue_length; /** * Queue version, use this to determine when the playlist has * changed. */ unsigned queue_version; /** MPD's current playback state */ enum mpd_state state; /** crossfade setting in seconds */ unsigned crossfade; /** Mixramp threshold in dB */ float mixrampdb; /** Mixramp extra delay in seconds */ float mixrampdelay; /** * If a song is currently selected (always the case when state * is PLAY or PAUSE), this is the position of the currently * playing song in the queue, beginning with 0. */ int song_pos; /** Song ID of the currently selected song */ int song_id; /** The same as song_pos, but for the next song to be played */ int next_song_pos; /** Song ID of the next song to be played */ int next_song_id; /** * Time in seconds that have elapsed in the currently * playing/paused song. */ unsigned elapsed_time; /** * Time in milliseconds that have elapsed in the currently * playing/paused song. */ unsigned elapsed_ms; /** length in seconds of the currently playing/paused song */ unsigned total_time; /** current bit rate in kbps */ unsigned kbit_rate; /** the current audio format */ struct mpd_audio_format audio_format; /** non-zero if MPD is updating, 0 otherwise */ unsigned update_id; /** the name of the current partition */ char *partition; /** error message */ char *error; }; struct mpd_status * mpd_status_begin(void) { struct mpd_status *status = malloc(sizeof(*status)); if (status == NULL) return NULL; status->volume = -1; status->repeat = false; status->random = false; status->single = MPD_SINGLE_OFF; status->consume = false; status->queue_version = 0; status->queue_length = 0; status->state = MPD_STATE_UNKNOWN; status->song_pos = -1; status->song_id = -1; status->next_song_pos = -1; status->next_song_id = -1; status->elapsed_time = 0; status->elapsed_ms = 0; status->total_time = 0; status->kbit_rate = 0; memset(&status->audio_format, 0, sizeof(status->audio_format)); status->crossfade = 0; status->mixrampdb = 100.0; status->mixrampdelay = -1.0; status->partition = NULL; status->error = NULL; status->update_id = 0; return status; } /** * Parses the fractional part of the "elapsed" response line. Up to * three digits are parsed. */ static unsigned parse_ms(const char *p) { unsigned ms; if (*p >= '0' && *p <= '9') ms = 100 * (*p++ - '0'); else return 0; if (*p >= '0' && *p <= '9') ms += 10 * (*p - '0'); else return ms; if (*p >= '0' && *p <= '9') ms += *p - '0'; return ms; } static enum mpd_state parse_mpd_state(const char *p) { if (strcmp(p, "play") == 0) return MPD_STATE_PLAY; else if (strcmp(p, "stop") == 0) return MPD_STATE_STOP; else if (strcmp(p, "pause") == 0) return MPD_STATE_PAUSE; else return MPD_STATE_UNKNOWN; } enum mpd_single_state mpd_parse_single_state(const char *p) { if (strcmp(p, "0") == 0) return MPD_SINGLE_OFF; else if (strcmp(p, "1") == 0) return MPD_SINGLE_ON; else if (strcmp(p, "oneshot") == 0) return MPD_SINGLE_ONESHOT; else return MPD_SINGLE_UNKNOWN; } const char * mpd_lookup_single_state(enum mpd_single_state state) { switch (state) { case MPD_SINGLE_OFF: return "0"; case MPD_SINGLE_ON: return "1"; case MPD_SINGLE_ONESHOT: return "oneshot"; case MPD_SINGLE_UNKNOWN: return NULL; } return NULL; } enum mpd_consume_state mpd_parse_consume_state(const char *p) { if (strcmp(p, "0") == 0) return MPD_CONSUME_OFF; else if (strcmp(p, "1") == 0) return MPD_CONSUME_ON; else if (strcmp(p, "oneshot") == 0) return MPD_CONSUME_ONESHOT; else return MPD_CONSUME_UNKNOWN; } const char * mpd_lookup_consume_state(enum mpd_consume_state state) { switch (state) { case MPD_CONSUME_OFF: return "0"; case MPD_CONSUME_ON: return "1"; case MPD_CONSUME_ONESHOT: return "oneshot"; default: return NULL; } } void mpd_status_feed(struct mpd_status *status, const struct mpd_pair *pair) { assert(status != NULL); assert(pair != NULL); if (strcmp(pair->name, "volume") == 0) status->volume = atoi(pair->value); else if (strcmp(pair->name, "repeat") == 0) status->repeat = !!atoi(pair->value); else if (strcmp(pair->name, "random") == 0) status->random = !!atoi(pair->value); else if (strcmp(pair->name, "single") == 0) status->single = mpd_parse_single_state(pair->value); else if (strcmp(pair->name, "consume") == 0) status->consume = mpd_parse_consume_state(pair->value); else if (strcmp(pair->name, "playlist") == 0) status->queue_version = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "playlistlength") == 0) status->queue_length = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "bitrate") == 0) status->kbit_rate = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "state") == 0) status->state = parse_mpd_state(pair->value); else if (strcmp(pair->name, "song") == 0) status->song_pos = (int)strtoimax(pair->value, NULL, 10); else if (strcmp(pair->name, "songid") == 0) status->song_id = (int)strtoimax(pair->value, NULL, 10); else if (strcmp(pair->name, "nextsong") == 0) status->next_song_pos = (int)strtoimax(pair->value, NULL, 10); else if (strcmp(pair->name, "nextsongid") == 0) status->next_song_id = (int)strtoimax(pair->value, NULL, 10); else if (strcmp(pair->name, "time") == 0) { char *endptr; status->elapsed_time = strtoul(pair->value, &endptr, 10); if (*endptr == ':') status->total_time = strtoul(endptr + 1, NULL, 10); if (status->elapsed_ms == 0) status->elapsed_ms = status->elapsed_time * 1000; } else if (strcmp(pair->name, "elapsed") == 0) { char *endptr; status->elapsed_ms = strtoul(pair->value, &endptr, 10) * 1000; if (*endptr == '.') status->elapsed_ms += parse_ms(endptr + 1); if (status->elapsed_time == 0) status->elapsed_time = status->elapsed_ms / 1000; } else if (strcmp(pair->name, "partition") == 0) { free(status->partition); status->partition = strdup(pair->value); } else if (strcmp(pair->name, "error") == 0) { free(status->error); status->error = strdup(pair->value); } else if (strcmp(pair->name, "xfade") == 0) status->crossfade = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "mixrampdb") == 0) status->mixrampdb = strtof(pair->value, NULL); else if (strcmp(pair->name, "mixrampdelay") == 0) status->mixrampdelay = strtof(pair->value, NULL); else if (strcmp(pair->name, "updating_db") == 0) status->update_id = strtoul(pair->value, NULL, 10); else if (strcmp(pair->name, "audio") == 0) mpd_parse_audio_format(&status->audio_format, pair->value); } void mpd_status_free(struct mpd_status * status) { assert(status != NULL); free(status->partition); free(status->error); free(status); } int mpd_status_get_volume(const struct mpd_status *status) { assert(status != NULL); return status->volume; } bool mpd_status_get_repeat(const struct mpd_status *status) { assert(status != NULL); return status->repeat; } bool mpd_status_get_random(const struct mpd_status *status) { assert(status != NULL); return status->random; } enum mpd_single_state mpd_status_get_single_state(const struct mpd_status *status) { assert(status != NULL); return status->single; } bool mpd_status_get_single(const struct mpd_status *status) { assert(status != NULL); return status->single == MPD_SINGLE_ONESHOT || status->single == MPD_SINGLE_ON; } enum mpd_consume_state mpd_status_get_consume_state(const struct mpd_status *status) { assert(status != NULL); return status->consume; } bool mpd_status_get_consume(const struct mpd_status *status) { assert(status != NULL); return status->consume == MPD_CONSUME_ONESHOT || status->consume == MPD_CONSUME_ON; } unsigned mpd_status_get_queue_length(const struct mpd_status *status) { assert(status != NULL); return status->queue_length; } unsigned mpd_status_get_queue_version(const struct mpd_status *status) { assert(status != NULL); return status->queue_version; } enum mpd_state mpd_status_get_state(const struct mpd_status *status) { assert(status != NULL); return status->state; } unsigned mpd_status_get_crossfade(const struct mpd_status *status) { assert(status != NULL); return status->crossfade; } float mpd_status_get_mixrampdb(const struct mpd_status *status) { assert(status != NULL); return status->mixrampdb; } float mpd_status_get_mixrampdelay(const struct mpd_status *status) { assert(status != NULL); return status->mixrampdelay; } int mpd_status_get_song_pos(const struct mpd_status *status) { assert(status != NULL); return status->song_pos; } int mpd_status_get_song_id(const struct mpd_status *status) { assert(status != NULL); return status->song_id; } int mpd_status_get_next_song_pos(const struct mpd_status *status) { assert(status != NULL); return status->next_song_pos; } int mpd_status_get_next_song_id(const struct mpd_status *status) { return status->next_song_id; } unsigned mpd_status_get_elapsed_time(const struct mpd_status *status) { assert(status != NULL); return status->elapsed_time; } unsigned mpd_status_get_elapsed_ms(const struct mpd_status *status) { assert(status != NULL); return status->elapsed_ms; } unsigned mpd_status_get_total_time(const struct mpd_status *status) { assert(status != NULL); return status->total_time; } unsigned mpd_status_get_kbit_rate(const struct mpd_status *status) { assert(status != NULL); return status->kbit_rate; } const struct mpd_audio_format * mpd_status_get_audio_format(const struct mpd_status *status) { assert(status != NULL); return !mpd_audio_format_is_empty(&status->audio_format) ? &status->audio_format : NULL; } unsigned mpd_status_get_update_id(const struct mpd_status *status) { assert(status != NULL); return status->update_id; } const char * mpd_status_get_partition(const struct mpd_status *status) { assert(status != NULL); return status->partition; } const char * mpd_status_get_error(const struct mpd_status *status) { assert(status != NULL); return status->error; } MusicPlayerDaemon-libmpdclient-5073329/src/sticker.c000066400000000000000000000174411505242054600223460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include "internal.h" #include "isend.h" #include "request.h" #include "run.h" #include #include #include #include bool mpd_send_sticker_set(struct mpd_connection *connection, const char *type, const char *uri, const char *name, const char *value) { return mpd_send_command(connection, "sticker", "set", type, uri, name, value, NULL); } bool mpd_run_sticker_set(struct mpd_connection *connection, const char *type, const char *uri, const char *name, const char *value) { return mpd_run_check(connection) && mpd_send_sticker_set(connection, type, uri, name, value) && mpd_response_finish(connection); } bool mpd_send_sticker_inc(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value) { return mpd_send_s_s_s_s_u_command(connection, "sticker", "inc", type, uri, name, value); } bool mpd_run_sticker_inc(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value) { return mpd_run_check(connection) && mpd_send_sticker_inc(connection, type, uri, name, value) && mpd_response_finish(connection); } bool mpd_send_sticker_dec(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value) { return mpd_send_s_s_s_s_u_command(connection, "sticker", "dec", type, uri, name, value); } bool mpd_run_sticker_dec(struct mpd_connection *connection, const char *type, const char *uri, const char *name, unsigned value) { return mpd_run_check(connection) && mpd_send_sticker_dec(connection, type, uri, name, value) && mpd_response_finish(connection); } bool mpd_send_sticker_delete(struct mpd_connection *connection, const char *type, const char *uri, const char *name) { assert(connection != NULL); assert(type != NULL); assert(uri != NULL); assert(name != NULL); return mpd_send_command(connection, "sticker", "delete", type, uri, name, NULL); } bool mpd_run_sticker_delete(struct mpd_connection *connection, const char *type, const char *uri, const char *name) { return mpd_run_check(connection) && mpd_send_sticker_delete(connection, type, uri, name) && mpd_response_finish(connection); } bool mpd_send_sticker_get(struct mpd_connection *connection, const char *type, const char *uri, const char *name) { assert(connection != NULL); assert(type != NULL); assert(uri != NULL); assert(name != NULL); return mpd_send_command(connection, "sticker", "get", type, uri, name, NULL); } bool mpd_send_sticker_list(struct mpd_connection *connection, const char *type, const char *uri) { assert(connection != NULL); assert(type != NULL); assert(uri != NULL); return mpd_send_command(connection, "sticker", "list", type, uri, NULL); } bool mpd_send_sticker_find(struct mpd_connection *connection, const char *type, const char *base_uri, const char *name) { assert(connection != NULL); assert(type != NULL); assert(name != NULL); if (base_uri == NULL) base_uri = ""; return mpd_send_command(connection, "sticker", "find", type, base_uri, name, NULL); } const char * mpd_parse_sticker(const char *input, size_t *name_length_r) { const char *eq; eq = strchr(input, '='); if (eq == NULL || eq == input) return NULL; *name_length_r = eq - input; return eq + 1; } struct mpd_pair * mpd_recv_sticker(struct mpd_connection *connection) { struct mpd_pair *pair; char *eq; pair = mpd_recv_pair_named(connection, "sticker"); if (pair == NULL) return NULL; pair->name = pair->value; eq = strchr(pair->value, '='); if (eq != NULL) { /* we shouldn't modify a const string, but in this case, we know that this points to the writable input buffer */ *eq = 0; pair->value = eq + 1; } else /* malformed response? what to do now? pretend nothing has happened... */ pair->value = ""; return pair; } void mpd_return_sticker(struct mpd_connection *connection, struct mpd_pair *pair) { mpd_return_pair(connection, pair); } bool mpd_send_stickernames(struct mpd_connection *connection) { assert(connection != NULL); return mpd_send_command(connection, "stickernames", NULL); } bool mpd_send_stickertypes(struct mpd_connection *connection) { assert(connection != NULL); return mpd_send_command(connection, "stickertypes", NULL); } bool mpd_send_stickernamestypes(struct mpd_connection *connection, const char *type) { assert(connection != NULL); return mpd_send_command(connection, "stickernamestypes", type, NULL); } bool mpd_sticker_search_begin(struct mpd_connection *connection, const char *type, const char *base_uri, const char *name) { assert(name != NULL); if (!mpd_request_begin(connection)) return false; if (base_uri == NULL) base_uri = ""; char *arg_base_uri = mpd_sanitize_arg(base_uri); if (arg_base_uri == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } char *arg_name = mpd_sanitize_arg(name); if (arg_name == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); free(arg_base_uri); return false; } const size_t size = 13 + strlen(type) + 2 + strlen(arg_base_uri) + 3 + strlen(arg_name) + 2; connection->request = malloc(size); if (connection->request == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); free(arg_base_uri); free(arg_name); return false; } snprintf(connection->request, size, "sticker find %s \"%s\" \"%s\"", type, arg_base_uri, arg_name); free(arg_base_uri); free(arg_name); return true; } static const char *get_sticker_oper_str(enum mpd_sticker_operator oper) { switch(oper) { case MPD_STICKER_OP_EQ: return "="; case MPD_STICKER_OP_GT: return ">"; case MPD_STICKER_OP_LT: return "<"; case MPD_STICKER_OP_EQ_INT: return "eq"; case MPD_STICKER_OP_GT_INT: return "gt"; case MPD_STICKER_OP_LT_INT: return "lt"; case MPD_STICKER_OP_CONTAINS: return "contains"; case MPD_STICKER_OP_STARTS_WITH: return "starts_with"; case MPD_STICKER_OP_UNKOWN: return NULL; } return NULL; } bool mpd_sticker_search_add_value_constraint(struct mpd_connection *connection, enum mpd_sticker_operator oper, const char *value) { assert(connection != NULL); assert(value != NULL); char *arg = mpd_sanitize_arg(value); if (arg == NULL) { mpd_error_code(&connection->error, MPD_ERROR_OOM); return false; } const char *oper_str = get_sticker_oper_str(oper); if (oper_str == NULL) return false; const size_t size = 1 + strlen(oper_str) + 2 + strlen(arg) + 2; char *dest = mpd_request_prepare_append(connection, size); if (dest == NULL) { free(arg); return false; } snprintf(dest, size, " %s \"%s\"", oper_str, arg); free(arg); return true; } static const char *get_sticker_sort_name(enum mpd_sticker_sort sort) { switch(sort) { case MPD_STICKER_SORT_URI: return "uri"; case MPD_STICKER_SORT_VALUE: return "value"; case MPD_STICKER_SORT_VALUE_INT: return "value_int"; case MPD_STICKER_SORT_UNKOWN: return NULL; } return NULL; } bool mpd_sticker_search_add_sort(struct mpd_connection *connection, enum mpd_sticker_sort sort, bool descending) { const char *sort_str = get_sticker_sort_name(sort); return mpd_request_add_sort(connection, sort_str, descending); } bool mpd_sticker_search_add_window(struct mpd_connection *connection, unsigned start, unsigned end) { return mpd_request_add_window(connection, start, end); } bool mpd_sticker_search_commit(struct mpd_connection *connection) { return mpd_request_commit(connection); } void mpd_sticker_search_cancel(struct mpd_connection *connection) { mpd_request_cancel(connection); } MusicPlayerDaemon-libmpdclient-5073329/src/stringnormalization.c000066400000000000000000000074721505242054600250220ustar00rootroot00000000000000// 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); } MusicPlayerDaemon-libmpdclient-5073329/src/sync.c000066400000000000000000000071111505242054600216470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "sync.h" #include "iasync.h" #include "socket.h" #include #include #include #include #ifndef _WIN32 #include #endif #include static enum mpd_async_event mpd_sync_poll(struct mpd_async *async, struct timeval *tv) { int fd; fd_set rfds, wfds, efds; int ret; enum mpd_async_event events; fd = mpd_async_get_fd(async); while (1) { events = mpd_async_events(async); if (events == 0) return 0; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (events & MPD_ASYNC_EVENT_READ) FD_SET(fd, &rfds); if (events & MPD_ASYNC_EVENT_WRITE) FD_SET(fd, &wfds); if (events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) FD_SET(fd, &efds); ret = select(fd + 1, &rfds, &wfds, &efds, tv); if (ret > 0) { if (!FD_ISSET(fd, &rfds)) events &= ~MPD_ASYNC_EVENT_READ; if (!FD_ISSET(fd, &wfds)) events &= ~MPD_ASYNC_EVENT_WRITE; if (!FD_ISSET(fd, &efds)) events &= ~(MPD_ASYNC_EVENT_HUP| MPD_ASYNC_EVENT_ERROR); return events; } if (ret == 0 || !mpd_socket_ignore_errno(mpd_socket_errno())) return 0; } } static bool mpd_sync_io(struct mpd_async *async, struct timeval *tv) { enum mpd_async_event events = mpd_sync_poll(async, tv); if (events) return mpd_async_io(async, events); else return false; } bool mpd_sync_send_command_v(struct mpd_async *async, const struct timeval *tv0, const char *command, va_list args) { struct timeval tv, *tvp; va_list copy; bool success; if (tv0 != NULL) { tv = *tv0; tvp = &tv; } else tvp = NULL; while (true) { va_copy(copy, args); success = mpd_async_send_command_v(async, command, copy); va_end(copy); if (success) return true; /* no characters were written to async buffer and no space will be made available with mpd_sync_io() hence we do not have enough space */ if ((mpd_async_events(async) & MPD_ASYNC_EVENT_WRITE) == 0) { mpd_async_set_error(async, MPD_ERROR_ARGUMENT, "Not enough buffer space for message"); return false; } if (!mpd_sync_io(async, tvp)) return false; } } bool mpd_sync_send_command(struct mpd_async *async, const struct timeval *tv, const char *command, ...) { va_list args; bool success; va_start(args, command); success = mpd_sync_send_command_v(async, tv, command, args); va_end(args); return success; } bool mpd_sync_flush(struct mpd_async *async, const struct timeval *tv0) { struct timeval tv, *tvp; if (tv0 != NULL) { tv = *tv0; tvp = &tv; } else tvp = NULL; if (!mpd_async_io(async, MPD_ASYNC_EVENT_WRITE)) return false; while (true) { enum mpd_async_event events = mpd_async_events(async); if ((events & MPD_ASYNC_EVENT_WRITE) == 0) /* no more pending writes */ return true; if (!mpd_sync_io(async, tvp)) return false; } } char * mpd_sync_recv_line(struct mpd_async *async, const struct timeval *tv0) { struct timeval tv, *tvp; char *line; if (tv0 != NULL) { tv = *tv0; tvp = &tv; } else tvp = NULL; while (true) { line = mpd_async_recv_line(async); if (line != NULL) return line; if (!mpd_sync_io(async, tvp)) return NULL; } } size_t mpd_sync_recv_raw(struct mpd_async *async, const struct timeval *tv0, void *dest, size_t length) { struct timeval tv, *tvp; if (tv0 != NULL) { tv = *tv0; tvp = &tv; } else tvp = NULL; while (true) { size_t nbytes = mpd_async_recv_raw(async, dest, length); if (nbytes > 0) return nbytes; if (!mpd_sync_io(async, tvp)) return 0; } } MusicPlayerDaemon-libmpdclient-5073329/src/sync.h000066400000000000000000000025751505242054600216650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project /*! \file * \brief Synchronous MPD connections * * This library provides synchronous access to a mpd_async object. * For all operations, you may provide a timeout. */ #ifndef MPD_SYNC_H #define MPD_SYNC_H #include #include #include #include struct timeval; struct mpd_async; /** * Synchronous wrapper for mpd_async_send_command_v(). */ bool mpd_sync_send_command_v(struct mpd_async *async, const struct timeval *tv, const char *command, va_list args); /** * Synchronous wrapper for mpd_async_send_command(). */ mpd_sentinel bool mpd_sync_send_command(struct mpd_async *async, const struct timeval *tv, const char *command, ...); /** * Sends all pending data from the output buffer to MPD. */ bool mpd_sync_flush(struct mpd_async *async, const struct timeval *tv); /** * Synchronous wrapper for mpd_async_recv_line(). */ char * mpd_sync_recv_line(struct mpd_async *async, const struct timeval *tv); /** * Synchronous wrapper for mpd_async_recv_raw() which waits until at * least one byte was received (or an error has occurred). * * @return the number of bytes copied to the destination buffer or 0 * on error */ size_t mpd_sync_recv_raw(struct mpd_async *async, const struct timeval *tv, void *dest, size_t length); #endif MusicPlayerDaemon-libmpdclient-5073329/src/tag.c000066400000000000000000000052521505242054600214520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include static const char *const mpd_tag_type_names[MPD_TAG_COUNT] = { [MPD_TAG_ARTIST] = "Artist", [MPD_TAG_ARTIST_SORT] = "ArtistSort", [MPD_TAG_ALBUM] = "Album", [MPD_TAG_ALBUM_SORT] = "AlbumSort", [MPD_TAG_ALBUM_ARTIST] = "AlbumArtist", [MPD_TAG_ALBUM_ARTIST_SORT] = "AlbumArtistSort", [MPD_TAG_TITLE] = "Title", [MPD_TAG_TRACK] = "Track", [MPD_TAG_NAME] = "Name", [MPD_TAG_GENRE] = "Genre", [MPD_TAG_DATE] = "Date", [MPD_TAG_COMPOSER] = "Composer", [MPD_TAG_PERFORMER] = "Performer", [MPD_TAG_COMMENT] = "Comment", [MPD_TAG_DISC] = "Disc", [MPD_TAG_LABEL] = "Label", [MPD_TAG_MUSICBRAINZ_ARTISTID] = "MUSICBRAINZ_ARTISTID", [MPD_TAG_MUSICBRAINZ_ALBUMID] = "MUSICBRAINZ_ALBUMID", [MPD_TAG_MUSICBRAINZ_ALBUMARTISTID] = "MUSICBRAINZ_ALBUMARTISTID", [MPD_TAG_MUSICBRAINZ_TRACKID] = "MUSICBRAINZ_TRACKID", [MPD_TAG_MUSICBRAINZ_RELEASETRACKID] = "MUSICBRAINZ_RELEASETRACKID", [MPD_TAG_MUSICBRAINZ_WORKID] = "MUSICBRAINZ_WORKID", [MPD_TAG_ORIGINAL_DATE] = "OriginalDate", [MPD_TAG_GROUPING] = "Grouping", [MPD_TAG_WORK] = "Work", [MPD_TAG_CONDUCTOR] = "Conductor", [MPD_TAG_COMPOSER_SORT] = "ComposerSort", [MPD_TAG_ENSEMBLE] = "Ensemble", [MPD_TAG_MOVEMENT] = "Movement", [MPD_TAG_MOVEMENTNUMBER] = "MovementNumber", [MPD_TAG_LOCATION] = "Location", [MPD_TAG_MOOD] = "Mood", [MPD_TAG_TITLE_SORT] = "TitleSort", [MPD_TAG_MUSICBRAINZ_RELEASEGROUPID] = "MUSICBRAINZ_RELEASEGROUPID", [MPD_TAG_SHOWMOVEMENT] = "ShowMovement", }; const char * mpd_tag_name(enum mpd_tag_type type) { if ((unsigned)type >= MPD_TAG_COUNT) return NULL; return mpd_tag_type_names[type]; } enum mpd_tag_type mpd_tag_name_parse(const char *name) { assert(name != NULL); for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) if (strcmp(name, mpd_tag_type_names[i]) == 0) return (enum mpd_tag_type)i; return MPD_TAG_UNKNOWN; } /** * This implementation is limited to ASCII letters. Cheap, and good * enough for us: all valid tag names are hard-coded above. */ static inline bool ignore_case_char_equals(const char a, const char b) { return (a & ~0x20) == (b & ~0x20); } static bool ignore_case_string_equals(const char *a, const char *b) { assert(a != NULL); assert(b != NULL); while (*a != 0) { if (!ignore_case_char_equals(*a, *b)) return false; ++a; ++b; } return *b == 0; } enum mpd_tag_type mpd_tag_name_iparse(const char *name) { assert(name != NULL); for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) if (ignore_case_string_equals(name, mpd_tag_type_names[i])) return (enum mpd_tag_type)i; return MPD_TAG_UNKNOWN; } MusicPlayerDaemon-libmpdclient-5073329/src/uri.h000066400000000000000000000006601505242054600215010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef MPD_URI_H #define MPD_URI_H #include #include static inline bool mpd_verify_uri(const char *uri) { assert(uri != NULL); return *uri != 0; } static inline bool mpd_verify_local_uri(const char *uri) { assert(uri != NULL); return mpd_verify_uri(uri) && *uri != '/' && uri[strlen(uri) - 1] != '/'; } #endif MusicPlayerDaemon-libmpdclient-5073329/test.ld000066400000000000000000000001141505242054600212340ustar00rootroot00000000000000# a minimal linker script for the configure-time check test { local: *; }; MusicPlayerDaemon-libmpdclient-5073329/test/000077500000000000000000000000001505242054600207175ustar00rootroot00000000000000MusicPlayerDaemon-libmpdclient-5073329/test/capture.c000066400000000000000000000026371505242054600225360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #include "capture.h" #include #include #include #include #ifdef _WIN32 # include # include /* for SSIZE_T */ typedef SSIZE_T ssize_t; #else # include # include #endif struct mpd_connection * test_capture_init(struct test_capture *tc) { int sv[2]; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) < 0) { perror("socketpair() failed"); return NULL; } tc->fd = sv[0]; struct mpd_async *async = mpd_async_new(sv[1]); if (async == NULL) { close(sv[0]); close(sv[1]); return NULL; } struct mpd_connection *c = mpd_connection_new_async(async, "OK MPD 0.21.0"); if (c == NULL) { mpd_async_free(async); close(sv[0]); return NULL; } return c; } void test_capture_deinit(struct test_capture *tc) { close(tc->fd); } const char * test_capture_receive(struct test_capture *tc) { ssize_t nbytes = recv(tc->fd, tc->buffer, sizeof(tc->buffer) - 1, MSG_DONTWAIT); if (nbytes < 0) { perror("recv() failed"); return NULL; } tc->buffer[nbytes] = 0; return tc->buffer; } bool test_capture_send(struct test_capture *tc, const char *response) { ssize_t nbytes = send(tc->fd, response, strlen(response), MSG_DONTWAIT); if (nbytes < 0) { perror("send() failed"); return false; } return true; } MusicPlayerDaemon-libmpdclient-5073329/test/capture.h000066400000000000000000000007171505242054600225400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright The Music Player Daemon Project #ifndef CAPTURE_H #define CAPTURE_H #include struct test_capture { int fd; char buffer[4096]; }; struct mpd_connection * test_capture_init(struct test_capture *tc); void test_capture_deinit(struct test_capture *tc); const char * test_capture_receive(struct test_capture *tc); bool test_capture_send(struct test_capture *tc, const char *response); #endif MusicPlayerDaemon-libmpdclient-5073329/test/main.c000066400000000000000000000200371505242054600220110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause // Copyright The Music Player Daemon Project #include #include #include #include #include #include #include #include #include #define BRIGHT 1 #define RED 31 #define GREEN 32 #define YELLOW 33 #define BG_BLACK 40 #define COLOR_CODE 0x1B #define LOG_INFO(x, ...) {printf(" [info]" x "\n", __VA_ARGS__);} #define LOG_WARNING(x, ...) \ {\ fprintf(stderr, "%c[%d;%d;%dm[WARNING](%s:%d) : " x "\n", COLOR_CODE, BRIGHT, YELLOW, BG_BLACK, __FILE__, __LINE__, __VA_ARGS__);\ printf("%c[%dm", 0x1B, 0);\ } #define LOG_ERROR(x, ...) \ {\ fprintf(stderr, "%c[%d;%d;%dm[ERROR](%s:%d) : " x "\n", COLOR_CODE, BRIGHT, RED, BG_BLACK, __FILE__, __LINE__, __VA_ARGS__);\ printf("%c[%dm", 0x1B, 0);\ } #define START_TEST(description, method, ...) \ {\ printf("[Start Test] " description "\n");\ if (method(__VA_ARGS__) < 0)\ printf("%c[%d;%d;%dm[End Test: ERROR]\n", COLOR_CODE, BRIGHT, RED, BG_BLACK);\ else\ printf("%c[%d;%d;%dm[End Test: OK]\n", COLOR_CODE, BRIGHT, GREEN, BG_BLACK);\ printf("%c[%dm", 0x1B, 0);\ } #define CHECK_CONNECTION(conn) \ if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { \ LOG_ERROR("%s", mpd_connection_get_error_message(conn)); \ return -1; \ } static int test_new_connection(struct mpd_connection **conn) { *conn = mpd_connection_new(NULL, 0, 30000); if (*conn == NULL) { LOG_ERROR("%s", "Out of memory"); return -1; } if (mpd_connection_get_error(*conn) != MPD_ERROR_SUCCESS) { LOG_ERROR("%s", mpd_connection_get_error_message(*conn)); mpd_connection_free(*conn); *conn = NULL; return -1; } return 0; } static int test_version(struct mpd_connection *conn) { int i, total = -1; for (i=0; i<3; ++i) { LOG_INFO("version[%i]: %i", i, mpd_connection_get_server_version(conn)[i]); total += mpd_connection_get_server_version(conn)[i]; } /* Check if at least one of the three number is positive */ return total; } static void print_audio_format(const struct mpd_audio_format *audio_format) { printf("sampleRate: %i\n", audio_format->sample_rate); printf("bits: %i\n", audio_format->bits); printf("channels: %i\n", audio_format->channels); } static void print_status(struct mpd_status *status) { const struct mpd_audio_format *audio_format; LOG_INFO("volume: %i", mpd_status_get_volume(status)); LOG_INFO("repeat: %i", mpd_status_get_repeat(status)); LOG_INFO("single: %i", mpd_status_get_single(status)); LOG_INFO("consume: %i", mpd_status_get_consume(status)); LOG_INFO("random: %i", mpd_status_get_random(status)); LOG_INFO("queue version: %u", mpd_status_get_queue_version(status)); LOG_INFO("queue length: %i", mpd_status_get_queue_length(status)); if (mpd_status_get_state(status) == MPD_STATE_PLAY || mpd_status_get_state(status) == MPD_STATE_PAUSE) { LOG_INFO("song: %i", mpd_status_get_song_pos(status)); LOG_INFO("elaspedTime: %i", mpd_status_get_elapsed_time(status)); LOG_INFO("elasped_ms: %u\n", mpd_status_get_elapsed_ms(status)); LOG_INFO("totalTime: %i", mpd_status_get_total_time(status)); LOG_INFO("bitRate: %i", mpd_status_get_kbit_rate(status)); } audio_format = mpd_status_get_audio_format(status); if (audio_format != NULL) print_audio_format(audio_format); } static void print_tag(const struct mpd_song *song, enum mpd_tag_type type, const char *label) { unsigned i = 0; const char *value; while ((value = mpd_song_get_tag(song, type, i++)) != NULL) LOG_INFO("%s: %s", label, value); } static void print_song(const struct mpd_song *song) { LOG_INFO("uri: %s\n", mpd_song_get_uri(song)); print_tag(song, MPD_TAG_ARTIST, "artist"); print_tag(song, MPD_TAG_ALBUM, "album"); print_tag(song, MPD_TAG_TITLE, "title"); print_tag(song, MPD_TAG_TRACK, "track"); print_tag(song, MPD_TAG_NAME, "name"); print_tag(song, MPD_TAG_DATE, "date"); if (mpd_song_get_duration(song) > 0) LOG_INFO("time: %i", mpd_song_get_duration(song)); if (mpd_song_get_duration_ms(song) > 0) LOG_INFO("duration: %i", mpd_song_get_duration_ms(song)); const struct mpd_audio_format *audio_format = mpd_song_get_audio_format(song); if (audio_format != NULL) print_audio_format(audio_format); LOG_INFO("pos: %u", mpd_song_get_pos(song)); } static int test_status(struct mpd_connection *conn) { struct mpd_status *status; status = mpd_run_status(conn); if (!status) { LOG_ERROR("%s", mpd_connection_get_error_message(conn)); return -1; } print_status(status); mpd_status_free(status); mpd_response_finish(conn); CHECK_CONNECTION(conn); return 0; } static int test_currentsong(struct mpd_connection *conn) { struct mpd_song *song; song = mpd_run_current_song(conn); if (song != NULL) { print_song(song); mpd_song_free(song); } mpd_response_finish(conn); CHECK_CONNECTION(conn); return 0; } static int test_list_status_currentsong(struct mpd_connection *conn) { struct mpd_status *status; const struct mpd_song *song; struct mpd_entity *entity; mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); CHECK_CONNECTION(conn); status = mpd_recv_status(conn); if (!status) { LOG_ERROR("%s", mpd_connection_get_error_message(conn)); return -1; } if (mpd_status_get_error(status)) { LOG_WARNING("status error: %s", mpd_status_get_error(status)); } print_status(status); mpd_status_free(status); mpd_response_next(conn); entity = mpd_recv_entity(conn); if (entity) { if (mpd_entity_get_type(entity) != MPD_ENTITY_TYPE_SONG) { LOG_ERROR("entity doesn't have the expected type (song)i :%d", mpd_entity_get_type(entity)); mpd_entity_free(entity); return -1; } song = mpd_entity_get_song(entity); print_song(song); mpd_entity_free(entity); } mpd_response_finish(conn); CHECK_CONNECTION(conn); return 0; } static int test_lsinfo(struct mpd_connection *conn, const char *path) { struct mpd_entity *entity; mpd_send_list_meta(conn, path); CHECK_CONNECTION(conn); while ((entity = mpd_recv_entity(conn)) != NULL) { const struct mpd_song *song; const struct mpd_directory *dir; const struct mpd_playlist *pl; switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_UNKNOWN: printf("Unknown type\n"); break; case MPD_ENTITY_TYPE_SONG: song = mpd_entity_get_song(entity); print_song (song); break; case MPD_ENTITY_TYPE_DIRECTORY: dir = mpd_entity_get_directory(entity); printf("directory: %s\n", mpd_directory_get_path(dir)); break; case MPD_ENTITY_TYPE_PLAYLIST: pl = mpd_entity_get_playlist(entity); LOG_INFO("playlist: %s", mpd_playlist_get_path(pl)); break; } mpd_entity_free(entity); } mpd_response_finish(conn); CHECK_CONNECTION(conn); return 0; } static int test_list_artists(struct mpd_connection *conn) { struct mpd_pair *pair; int first = 1; mpd_search_db_tags(conn, MPD_TAG_ARTIST); mpd_search_commit(conn); CHECK_CONNECTION(conn); LOG_INFO("%s: ", "Artists list"); while ((pair = mpd_recv_pair_tag(conn, MPD_TAG_ARTIST)) != NULL) { if (first) { printf(" %s", pair->value); first = 0; } else { printf(", %s", pair->value); } mpd_return_pair(conn, pair); } printf("\n"); mpd_response_finish(conn); CHECK_CONNECTION(conn); return 0; } static int test_close_connection(struct mpd_connection *conn) { mpd_connection_free(conn); return 0; } int main(int argc, char ** argv) { struct mpd_connection *conn = NULL; const char *lsinfo_path = "/"; if (argc==2) lsinfo_path = argv[1]; START_TEST("Test connection to MPD server", test_new_connection, &conn); if (!conn) return -1; START_TEST("Check MPD versions", test_version, conn); START_TEST("'status' command", test_status, conn); START_TEST("'currentsong' command", test_currentsong, conn); START_TEST("List commands: 'status' and 'currentsong'", test_list_status_currentsong, conn); START_TEST("'lsinfo' command", test_lsinfo, conn, lsinfo_path); START_TEST("'list artist' command", test_list_artists, conn); START_TEST("Test connection closing", test_close_connection, conn); return 0; } MusicPlayerDaemon-libmpdclient-5073329/test/meson.build000066400000000000000000000006101505242054600230560ustar00rootroot00000000000000executable('main', 'main.c', dependencies: [ libmpdclient_dep, ]) test('t_iso8601', executable('t_iso8601', 't_iso8601.c', '../src/iso8601.c', include_directories: inc, dependencies: [ check_dep, ])) test('t_commands', executable('t_commands', 't_commands.c', 'capture.c', include_directories: inc, dependencies: [ libmpdclient_dep, check_dep, ])) MusicPlayerDaemon-libmpdclient-5073329/test/t_commands.c000066400000000000000000000331021505242054600232060ustar00rootroot00000000000000#include "capture.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SETLOCALE #include #endif static void abort_command(struct test_capture *capture, struct mpd_connection *connection) { test_capture_send(capture, "ACK [5@0] {} cancel\n"); mpd_response_finish(connection); ck_assert(mpd_connection_clear_error(connection)); } START_TEST(test_capabilities_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_allowed_commands(c)); ck_assert_str_eq(test_capture_receive(&capture), "commands\n"); abort_command(&capture, c); ck_assert(mpd_send_disallowed_commands(c)); ck_assert_str_eq(test_capture_receive(&capture), "notcommands\n"); abort_command(&capture, c); ck_assert(mpd_send_list_url_schemes(c)); ck_assert_str_eq(test_capture_receive(&capture), "urlhandlers\n"); abort_command(&capture, c); ck_assert(mpd_send_list_tag_types(c)); ck_assert_str_eq(test_capture_receive(&capture), "tagtypes\n"); abort_command(&capture, c); static const enum mpd_tag_type types[] = { MPD_TAG_COMMENT, MPD_TAG_PERFORMER, MPD_TAG_MUSICBRAINZ_RELEASETRACKID, }; ck_assert(mpd_send_disable_tag_types(c, types, 3)); ck_assert_str_eq(test_capture_receive(&capture), "tagtypes disable Comment Performer MUSICBRAINZ_RELEASETRACKID\n"); abort_command(&capture, c); ck_assert(mpd_send_enable_tag_types(c, types, 3)); ck_assert_str_eq(test_capture_receive(&capture), "tagtypes enable Comment Performer MUSICBRAINZ_RELEASETRACKID\n"); abort_command(&capture, c); ck_assert(mpd_send_clear_tag_types(c)); ck_assert_str_eq(test_capture_receive(&capture), "tagtypes \"clear\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_queue_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_list_queue_meta(c)); ck_assert_str_eq(test_capture_receive(&capture), "playlistinfo\n"); abort_command(&capture, c); ck_assert(mpd_send_list_queue_range_meta(c, 0, 1)); ck_assert_str_eq(test_capture_receive(&capture), "playlistinfo \"0:1\"\n"); abort_command(&capture, c); ck_assert(mpd_send_list_queue_range_meta(c, 42, UINT_MAX)); ck_assert_str_eq(test_capture_receive(&capture), "playlistinfo \"42:\"\n"); abort_command(&capture, c); ck_assert(mpd_send_get_queue_song_pos(c, 42)); ck_assert_str_eq(test_capture_receive(&capture), "playlistinfo \"42\"\n"); abort_command(&capture, c); ck_assert(mpd_send_queue_changes_meta(c, 42)); ck_assert_str_eq(test_capture_receive(&capture), "plchanges \"42\"\n"); abort_command(&capture, c); ck_assert(mpd_send_queue_changes_meta_range(c, 42, 6, 7)); ck_assert_str_eq(test_capture_receive(&capture), "plchanges \"42\" \"6:7\"\n"); abort_command(&capture, c); ck_assert(mpd_send_queue_changes_brief(c, 42)); ck_assert_str_eq(test_capture_receive(&capture), "plchangesposid \"42\"\n"); abort_command(&capture, c); ck_assert(mpd_send_queue_changes_meta_range(c, 42, 6, UINT_MAX)); ck_assert_str_eq(test_capture_receive(&capture), "plchanges \"42\" \"6:\"\n"); abort_command(&capture, c); ck_assert(mpd_send_add_tag_id(c, 42, MPD_TAG_COMMENT, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "addtagid \"42\" \"Comment\" \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_clear_tag_id(c, 42, MPD_TAG_COMMENT)); ck_assert_str_eq(test_capture_receive(&capture), "cleartagid \"42\" \"Comment\"\n"); abort_command(&capture, c); ck_assert(mpd_send_clear_all_tags_id(c, 42)); ck_assert_str_eq(test_capture_receive(&capture), "cleartagid \"42\"\n"); abort_command(&capture, c); ck_assert(mpd_send_range_id(c, 42, 0, 666)); ck_assert_str_eq(test_capture_receive(&capture), "rangeid \"42\" \"0.000:666.000\"\n"); abort_command(&capture, c); ck_assert(mpd_send_range_id(c, 42, 6, -1)); ck_assert_str_eq(test_capture_receive(&capture), "rangeid \"42\" \"6.000:\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_playlist_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_list_playlists(c)); ck_assert_str_eq(test_capture_receive(&capture), "listplaylists\n"); abort_command(&capture, c); ck_assert(mpd_send_list_playlist(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "listplaylist \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_list_playlist_meta(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "listplaylistinfo \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_playlist_clear(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "playlistclear \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_playlist_add(c, "foo", "bar")); ck_assert_str_eq(test_capture_receive(&capture), "playlistadd \"foo\" \"bar\"\n"); abort_command(&capture, c); ck_assert(mpd_send_save(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "save \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_load(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "load \"foo\"\n"); abort_command(&capture, c); ck_assert(mpd_send_load_range(c, "foo", 2, 5)); ck_assert_str_eq(test_capture_receive(&capture), "load \"foo\" \"2:5\"\n"); abort_command(&capture, c); ck_assert(mpd_send_load_range(c, "foo", 2, UINT_MAX)); ck_assert_str_eq(test_capture_receive(&capture), "load \"foo\" \"2:\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_database_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_list_files(c, "nfs://foo/bar")); ck_assert_str_eq(test_capture_receive(&capture), "listfiles \"nfs://foo/bar\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_search) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); /* start a search, but cancel it */ ck_assert(mpd_search_queue_songs(c, false)); ck_assert(mpd_search_add_uri_constraint(c, MPD_OPERATOR_DEFAULT, "foo")); mpd_search_cancel(c); /* start a new search */ ck_assert(mpd_search_db_songs(c, true)); ck_assert(mpd_search_add_base_constraint(c, MPD_OPERATOR_DEFAULT, "foo")); ck_assert(mpd_search_add_tag_constraint(c, MPD_OPERATOR_DEFAULT, MPD_TAG_ARTIST, "Queen")); ck_assert(mpd_search_add_any_tag_constraint(c, MPD_OPERATOR_DEFAULT, "Foo")); ck_assert(mpd_search_add_sort_tag(c, MPD_TAG_DATE, false)); ck_assert(mpd_search_add_window(c, 7, 9)); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "find base \"foo\" Artist \"Queen\" any \"Foo\" sort Date window 7:9\n"); abort_command(&capture, c); /* another search */ ck_assert(mpd_search_db_songs(c, false)); ck_assert(mpd_search_add_base_constraint(c, MPD_OPERATOR_DEFAULT, "foo")); ck_assert(mpd_search_add_sort_tag(c, MPD_TAG_DATE, false)); ck_assert(mpd_search_add_window(c, 7, 9)); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "search base \"foo\" sort Date window 7:9\n"); abort_command(&capture, c); /* check backslash escape */ ck_assert(mpd_search_db_songs(c, false)); ck_assert(mpd_search_add_tag_constraint(c, MPD_OPERATOR_DEFAULT, MPD_TAG_ARTIST, "double quote: \" and backslash: \\")); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "search Artist \"double quote: \\\" and backslash: \\\\\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_expression) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_search_db_songs(c, true)); ck_assert(mpd_search_add_expression(c, "(Artist == \"Queen\")")); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "find \"(Artist == \\\"Queen\\\")\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_list) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_search_db_tags(c, MPD_TAG_ARTIST)); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "list Artist\n"); abort_command(&capture, c); ck_assert(mpd_search_db_tags(c, MPD_TAG_ALBUM)); ck_assert(mpd_search_add_group_tag(c, MPD_TAG_ARTIST)); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "list Album group Artist\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_count) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_count_db_songs(c)); ck_assert(mpd_search_add_tag_constraint(c, MPD_OPERATOR_DEFAULT, MPD_TAG_ARTIST, "Queen")); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "count Artist \"Queen\"\n"); abort_command(&capture, c); ck_assert(mpd_count_db_songs(c)); ck_assert(mpd_search_add_tag_constraint(c, MPD_OPERATOR_DEFAULT, MPD_TAG_ARTIST, "Queen")); ck_assert(mpd_search_add_group_tag(c, MPD_TAG_ALBUM)); ck_assert(mpd_search_commit(c)); ck_assert_str_eq(test_capture_receive(&capture), "count Artist \"Queen\" group Album\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_player_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_seek_pos(c, 2, 120)); ck_assert_str_eq(test_capture_receive(&capture), "seek \"2\" \"120\"\n"); abort_command(&capture, c); ck_assert(mpd_send_seek_id(c, 2, 120)); ck_assert_str_eq(test_capture_receive(&capture), "seekid \"2\" \"120\"\n"); abort_command(&capture, c); ck_assert(mpd_send_seek_id_float(c, 2, 120.5)); ck_assert_str_eq(test_capture_receive(&capture), "seekid \"2\" \"120.500\"\n"); abort_command(&capture, c); ck_assert(mpd_send_seek_current(c, 42, false)); ck_assert_str_eq(test_capture_receive(&capture), "seekcur \"42.000\"\n"); abort_command(&capture, c); ck_assert(mpd_send_seek_current(c, 42, true)); ck_assert_str_eq(test_capture_receive(&capture), "seekcur \"+42.000\"\n"); abort_command(&capture, c); ck_assert(mpd_send_seek_current(c, -42, false)); ck_assert_str_eq(test_capture_receive(&capture), "seekcur \"-42.000\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST START_TEST(test_mount_commands) { struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_list_mounts(c)); ck_assert_str_eq(test_capture_receive(&capture), "listmounts\n"); abort_command(&capture, c); ck_assert(mpd_send_mount(c, "foo", "nfs://server/share")); ck_assert_str_eq(test_capture_receive(&capture), "mount \"foo\" \"nfs://server/share\"\n"); abort_command(&capture, c); ck_assert(mpd_send_unmount(c, "foo")); ck_assert_str_eq(test_capture_receive(&capture), "unmount \"foo\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); } END_TEST #ifdef HAVE_SETLOCALE START_TEST(test_locale) { /* choosing a locale that uses the comma instead of the dot as the decimal separator to see if this affects libmpdclient (it should not because MPD expects the dot) */ setlocale(LC_ALL, "de_DE@UTF-8"); struct test_capture capture; struct mpd_connection *c = test_capture_init(&capture); ck_assert(mpd_send_seek_current(c, -42.5, false)); ck_assert_str_eq(test_capture_receive(&capture), "seekcur \"-42.500\"\n"); abort_command(&capture, c); mpd_connection_free(c); test_capture_deinit(&capture); setlocale(LC_ALL, "C"); } END_TEST #endif // HAVE_SETLOCALE static Suite * create_suite(void) { Suite *s = suite_create("commands"); TCase *tc_capabilities = tcase_create("capabilities"); tcase_add_test(tc_capabilities, test_capabilities_commands); suite_add_tcase(s, tc_capabilities); TCase *tc_queue = tcase_create("queue"); tcase_add_test(tc_queue, test_queue_commands); suite_add_tcase(s, tc_queue); TCase *tc_playlist = tcase_create("playlist"); tcase_add_test(tc_playlist, test_playlist_commands); suite_add_tcase(s, tc_playlist); TCase *tc_database = tcase_create("database"); tcase_add_test(tc_database, test_database_commands); suite_add_tcase(s, tc_database); TCase *tc_search = tcase_create("search"); tcase_add_test(tc_search, test_search); tcase_add_test(tc_search, test_expression); tcase_add_test(tc_search, test_list); tcase_add_test(tc_search, test_count); suite_add_tcase(s, tc_search); TCase *tc_player = tcase_create("player"); tcase_add_test(tc_player, test_player_commands); suite_add_tcase(s, tc_player); TCase *tc_mount = tcase_create("mount"); tcase_add_test(tc_mount, test_mount_commands); suite_add_tcase(s, tc_mount); #ifdef HAVE_SETLOCALE TCase *tc_locale = tcase_create("locale"); tcase_add_test(tc_locale, test_locale); suite_add_tcase(s, tc_locale); #endif // HAVE_SETLOCALE return s; } int main(void) { Suite *s = create_suite(); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); int number_failed = srunner_ntests_failed(sr); srunner_free(sr); return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } MusicPlayerDaemon-libmpdclient-5073329/test/t_iso8601.c000066400000000000000000000014421505242054600225200ustar00rootroot00000000000000#include "iso8601.h" #include #include #include #include START_TEST(test_iso8601) { char buffer[64]; time_t t, now; bool success; now = time(NULL); success = iso8601_datetime_format(buffer, sizeof(buffer), now); ck_assert(success); t = iso8601_datetime_parse(buffer); ck_assert_int_eq(t, now); } END_TEST static Suite * create_suite(void) { Suite *s = suite_create("iso8601"); TCase *tc_core = tcase_create("Core"); tcase_add_test(tc_core, test_iso8601); suite_add_tcase(s, tc_core); return s; } int main(void) { Suite *s = create_suite(); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); int number_failed = srunner_ntests_failed(sr); srunner_free(sr); return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }