update r18 plug adblock rule

This commit is contained in:
JamesonHuang 2016-02-16 15:48:49 +08:00
parent ac497e45c4
commit d388c17999
359 changed files with 729038 additions and 387521 deletions

33
1_6.h12_dev/libmpdclient/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
*.cache
aclocal.m4
config.*
configure
build
*.la
*.lo
*.loT
*.o
example
libtool
stamp-*
Makefile
Makefile.in
.libs
.deps
.dirstamp
.stgit*
*~
/m4/libtool.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
test/test
/*.pc
doc/doxygen.conf
doc/api
*.exe
*.tar.*
include/mpd/version.h
test/t_iso8601

View File

@ -0,0 +1,20 @@
libmpdclient authors
====================
libmpdclient was developed by many people, including:
Max Kellermann <max@duempel.org>
Marc Pavot <marc.pavot@gmail.com>
Martijn Koedam <qball@sarine.nl>
Avuton Olrich <avuton@gmail.com>
Andrzej Rybczak <electricityispower@gmail.com>
Roman Nuritdinov <ky6uk.kun@gmail.com>
Romain Bignon <romain@peerfuse.org>
Former libmpdclient developers
------------------------------
J. Alexander Treuman <jat@spatialrift.net>
Warren Dukes <warren.dukes@gmail.com>
Eric Wong

View File

@ -0,0 +1,26 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.

View File

@ -0,0 +1,41 @@
libmpdclient INSTALL
====================
Requirements
------------
* a C99 compliant compiler (e.g. gcc)
* make
Compiling libmpdclient
----------------------
Download and unpack the source code. In the libmpdclient directory,
type:
./configure
The configure option "--help" lists all available compile time
options.
Compile and install:
make
sudo make install
Compiling with dietlibc
-----------------------
Use the "diet" wrapper as your C compiler:
CC="diet -Os gcc -nostdinc" ./configure --disable-shared
Compiling for Windows
---------------------
With mingw32, you can easily cross-compile libmpdclient for Windows:
./configure --host=i586-mingw32msvc && make

View File

@ -0,0 +1,182 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign 1.11 dist-xz subdir-objects
mpdincludedir = $(includedir)/mpd
mpdinclude_HEADERS = \
include/mpd/async.h \
include/mpd/audio_format.h \
include/mpd/client.h \
include/mpd/capabilities.h \
include/mpd/compiler.h \
include/mpd/connection.h \
include/mpd/database.h \
include/mpd/directory.h \
include/mpd/entity.h \
include/mpd/error.h \
include/mpd/idle.h \
include/mpd/list.h \
include/mpd/mixer.h \
include/mpd/parser.h \
include/mpd/password.h \
include/mpd/player.h \
include/mpd/playlist.h \
include/mpd/protocol.h \
include/mpd/queue.h \
include/mpd/recv.h \
include/mpd/response.h \
include/mpd/send.h \
include/mpd/status.h \
include/mpd/stats.h \
include/mpd/tag.h \
include/mpd/output.h \
include/mpd/pair.h \
include/mpd/search.h \
include/mpd/song.h \
include/mpd/sticker.h \
include/mpd/settings.h \
include/mpd/message.h \
include/mpd/version.h
AM_CPPFLAGS += -I$(srcdir)/include -Iinclude
lib_LTLIBRARIES = src/libmpdclient.la
src_libmpdclient_la_SOURCES = \
src/async.c src/iasync.h \
src/buffer.h \
src/internal.h \
src/ierror.c src/ierror.h \
src/resolver.c src/resolver.h \
src/capabilities.c \
src/connection.c \
src/database.c \
src/directory.c \
src/rdirectory.c \
src/error.c \
src/fd_util.c src/fd_util.h \
src/output.c \
src/coutput.c \
src/entity.c \
src/idle.c \
src/iso8601.h \
src/iso8601.c \
src/list.c \
src/mixer.c \
src/parser.c \
src/password.c \
src/player.c \
src/playlist.c \
src/rplaylist.c \
src/cplaylist.c \
src/queue.c \
src/quote.c src/quote.h \
src/recv.c \
src/response.c \
src/run.c src/run.h \
src/search.c \
src/send.c src/isend.h \
src/socket.c src/socket.h \
src/song.c \
src/status.c \
src/cstatus.c \
src/stats.c \
src/cstats.c \
src/sync.c src/sync.h \
src/tag.c \
src/sticker.c \
src/settings.c \
src/message.c \
src/cmessage.c \
src/uri.h
src_libmpdclient_la_LDFLAGS = -version-info @LIBMPDCLIENT_LIBTOOL_VERSION@ \
-no-undefined
if HAVE_GNU_LD
src_libmpdclient_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libmpdclient.ld
endif
noinst_PROGRAMS = src/example test/test
src_example_SOURCES = src/example.c
src_example_LDADD = src/libmpdclient.la
test_test_SOURCES = test/main.c
test_test_LDADD = src/libmpdclient.la
#
# Test suite
#
TESTS = test/t_iso8601
check_PROGRAMS = $(TESTS)
test_t_iso8601_SOURCES = test/t_iso8601.c src/iso8601.c
test_t_iso8601_CPPFLAGS = -I$(srcdir)/src $(AM_CPPFLAGS)
#
# sparse
#
SPARSE = sparse
SPARSE_FLAGS =
SPARSE_CPPFLAGS = $(DEFAULT_INCLUDES) \
-D__CHAR_BIT__=8
-I$(shell $(CC) -print-file-name=include) \
-I$(shell $(CC) -print-file-name=include-fixed)
sparse-check:
$(SPARSE) -I. $(CFLAGS) $(AM_CPPFLAGS) $(SPARSE_FLAGS) $(SPARSE_CPPFLAGS) $(addprefix $(srcdir)/,$(src_libmpdclient_la_SOURCES))
#
# Documentation
#
doc_DATA = README COPYING NEWS
if DOXYGEN
doc/api/html/index.html: doc/doxygen.conf
@mkdir -p $(@D)
$(DOXYGEN) $<
all-local: doc/api/html/index.html
mostlyclean-local:
rm -rf doc/api
install-data-local: doc/api/html/index.html
$(mkinstalldirs) $(DESTDIR)$(docdir)/html
$(INSTALL_DATA) -c -m 644 doc/api/html/*.* \
$(DESTDIR)$(docdir)/html
uninstall-local:
rm -f $(DESTDIR)$(docdir)/html/*.*
upload: doc/api/html/index.html
rsync -vpruz --delete doc/api/html/ \
max@www.musicpd.org:/var/www/mpd/doc/libmpdclient/ \
--chmod=Dug+rwx,Do+rx,Fug+rw,Fo+r
endif
#
# Installation
#
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmpdclient.pc
vapidir = $(datadir)/vala/vapi
vapi_DATA = vapi/libmpdclient.vapi
#
# Distribution
#
EXTRA_DIST = \
libmpdclient.ld \
libmpdclient.pc.in \
autogen.sh \
vapi/libmpdclient.vapi \
$(doc_DATA)

View File

@ -0,0 +1,85 @@
libmpdclient 2.11 (not yet released)
* add space before "window" search argument
* detect getaddrinfo() at configure time
* add support for ArtistSort and AlbumArtistSort tags
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

View File

@ -0,0 +1,13 @@
libmpdclient
http://www.musicpd.org
This is a library for interfacing Music Player Daemon (MPD).
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.
For the full license, see COPYING.

View File

@ -0,0 +1,14 @@
#!/bin/sh -e
rm -rf config.cache build
mkdir build
libtoolize --force $LIBTOOLIZE_FLAGS
aclocal -I m4
autoconf
autoheader
automake --add-missing $AUTOMAKE_FLAGS
if test x$NOCONFIGURE = x; then
echo "./configure $*"
./configure $*
fi

View File

@ -0,0 +1,161 @@
AC_PREREQ(2.60)
AC_INIT(libmpdclient, 2.11, musicpd-dev-team@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/connection.c])
AC_CONFIG_AUX_DIR(build)
AM_INIT_AUTOMAKE([foreign 1.11 dist-xz subdir-objects silent-rules])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_SUBST(MAJOR_VERSION,2)
AC_SUBST(MINOR_VERSION,11)
AC_SUBST(PATCH_VERSION,0)
LIBMPDCLIENT_LIBTOOL_VERSION=2:11:0
AC_SUBST(LIBMPDCLIENT_LIBTOOL_VERSION)
# Remove the check for c++ and fortran compiler
m4_defun([_LT_AC_LANG_CXX_CONFIG], [:])
m4_defun([_LT_AC_LANG_F77_CONFIG], [:])
dnl Check for programs
AC_PROG_CC_C99
AC_PROG_INSTALL
AC_PROG_LD
AM_CONDITIONAL(HAVE_GNU_LD, test x$with_gnu_ld = xyes)
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
dnl
dnl initialize variables
dnl
set -- $CFLAGS
dnl
dnl OS specific defaults
dnl
AC_CANONICAL_HOST
case "$host_os" in
mingw32* | windows*)
LIBS="$LIBS -lws2_32"
;;
esac
dnl
dnl Check for libraries
dnl
AC_SEARCH_LIBS([socket], [network socket])
dnl
dnl build options
dnl
AC_ARG_ENABLE(documentation,
AS_HELP_STRING([--disable-documentation],
[Disable API doc generation @<:@default=enabled@:>@]),,
[enable_documentation=yes])
if test "x$enable_documentation" = xyes; then
AC_PATH_PROG(DOXYGEN, doxygen)
if test x$DOXYGEN = x; then
AC_MSG_ERROR([doxygen not found])
fi
AC_SUBST(DOXYGEN)
fi
AM_CONDITIONAL(DOXYGEN, test x$enable_documentation = xyes)
AC_ARG_ENABLE(tcp,
AS_HELP_STRING([--disable-tcp],
[Disable TCP support @<:@default=enabled@:>@]),,
[enable_tcp=yes])
if test "x$enable_tcp" = xyes; then
AC_DEFINE([ENABLE_TCP], 1, [Define to enable TCP support])
AC_SEARCH_LIBS([gethostbyname], [nsl])
AC_CHECK_FUNCS([getaddrinfo])
fi
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--enable-werror],
[Treat warnings as errors @<:@default=disabled@:>@]),
enable_werror=no)
if test "x$enable_werror" = xyes; then
AM_CFLAGS="$AM_CFLAGS -Werror -pedantic-errors"
fi
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[Enable debugging @<:@default=disabled@:>@]),
enable_debug=no)
if test "x$enable_debug" = xno; then
AM_CFLAGS="$AM_CFLAGS -DNDEBUG"
fi
dnl
dnl CFLAGS
dnl
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_CPPFLAGS)
WANTED_CFLAGS="-Wall -W -Wextra -Wno-deprecated-declarations -Wmissing-prototypes -Wshadow -Wpointer-arith -Wstrict-prototypes -Wcast-qual -Wwrite-strings"
for flag in $WANTED_CFLAGS ; do
AX_CHECK_COMPILER_FLAGS([$flag], [CFLAGS="$CFLAGS $flag"],)
done
dnl
dnl Compile-time options
dnl
AC_ARG_WITH([default-socket],
AC_HELP_STRING([--with-default-socket=PATH],
[default path of the socket file @<:@/var/run/mpd/socket@:>@]),,
[with_default_socket=auto])
if test x$with_default_socket = xauto; then
case "$host_os" in
mingw32* | windows*)
# no UNIX domain sockets on WIN32
with_default_socket=no
;;
*)
with_default_socket=/var/run/mpd/socket
;;
esac
fi
if test x$with_default_socket != xno; then
AC_DEFINE_UNQUOTED([DEFAULT_SOCKET], ["$with_default_socket"],
[Default UNIX socket path])
fi
AC_ARG_WITH([default-host],
AC_HELP_STRING([--with-default-host=ARG],
[default MPD host @<:@localhost@:>@]),,
[with_default_host=localhost])
AC_DEFINE_UNQUOTED([DEFAULT_HOST], ["$with_default_host"], [Default MPD host])
AC_ARG_WITH([default-port],
AC_HELP_STRING([--with-default-port=ARG],
[default MPD port @<:@6600@:>@]),,
[with_default_port=6600])
AC_DEFINE_UNQUOTED([DEFAULT_PORT], [$with_default_port], [Default MPD port])
dnl
dnl Done
dnl
AC_OUTPUT([Makefile include/mpd/version.h libmpdclient.pc doc/doxygen.conf])

View File

@ -0,0 +1,110 @@
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = libmpdclient
PROJECT_NUMBER = @VERSION@
OUTPUT_DIRECTORY = doc/api
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = 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
#---------------------------------------------------------------------------
# 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 = NO
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View File

@ -0,0 +1,215 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/error.h>
#include <mpd/compiler.h>
#include <stdbool.h>
#include <stdarg.h>
/**
* 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_is_alive() returns false, 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
*
* @since libmpdclient 2.10
*/
void 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 argument list
* @return true on success, false if the buffer is full
*/
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
* @return true on success, false if the buffer is full
*/
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.
*
* @param async the connection
* @return a line on success, NULL otherwise
*/
mpd_malloc
char *
mpd_async_recv_line(struct mpd_async *async);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,87 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <stdint.h>
enum {
/**
* 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.
*/
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.
*
* @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.
*/
uint8_t channels;
/** reserved for future use */
uint16_t reserved0;
/** reserved for future use */
uint32_t reserved1;
};
#endif

View File

@ -0,0 +1,145 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/recv.h>
#include <mpd/compiler.h>
#include <stdbool.h>
struct mpd_connection;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Requests a list of supported and allowed. Use
* mpd_recv_pair_named() 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_pair_named() 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_commands() or mpd_send_notcommands().
*
* 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_pair_named() 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_urlhandlers() 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_pair_named()
* 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);
/**
* Receives the next tag type name. Call this in a loop after
* mpd_send_tagtypes().
*
* 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");
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,75 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \file
* \brief MPD client library
*
* This is a client library for the Music Player Daemon, 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@duempel.org)
*/
#ifndef MPD_CLIENT_H
#define MPD_CLIENT_H
#include <mpd/audio_format.h>
#include <mpd/capabilities.h>
#include <mpd/connection.h>
#include <mpd/database.h>
#include <mpd/directory.h>
#include <mpd/entity.h>
#include <mpd/idle.h>
#include <mpd/list.h>
#include <mpd/message.h>
#include <mpd/mixer.h>
#include <mpd/output.h>
#include <mpd/pair.h>
#include <mpd/password.h>
#include <mpd/player.h>
#include <mpd/playlist.h>
#include <mpd/queue.h>
#include <mpd/recv.h>
#include <mpd/response.h>
#include <mpd/search.h>
#include <mpd/send.h>
#include <mpd/settings.h>
#include <mpd/song.h>
#include <mpd/stats.h>
#include <mpd/status.h>
#include <mpd/sticker.h>
#include <mpd/version.h>
#endif

View File

@ -0,0 +1,64 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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))
#define mpd_printf(a,b) __attribute__((format(printf, a, b)))
#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

View File

@ -0,0 +1,283 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/protocol.h>
#include <mpd/error.h>
#include <mpd/compiler.h>
#include <stdbool.h>
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().
*
* 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().
*/
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
*
* @since libmpdclient 2.10
*/
void 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.
*/
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

View File

@ -0,0 +1,163 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
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.
*
* @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 the directory to be listed
* @return true on success, false on error
*/
bool
mpd_send_list_meta(struct mpd_connection *connection, const char *path);
/**
* 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 the 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

View File

@ -0,0 +1,131 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
#include <time.h>
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

View File

@ -0,0 +1,168 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/song.h>
#include <mpd/directory.h>
#include <mpd/client.h>
#include <mpd/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 of
* 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 of
* 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 of
* mpd_entity_get_type() has returned #MPD_ENTITY_TYPE_PLAYLIST.
*
* @return the directory 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

View File

@ -0,0 +1,76 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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

View File

@ -0,0 +1,206 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
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.
*/
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,
};
#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).
*/
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 a positive job id on success, 0 on error
*/
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.
*/
bool
mpd_send_noidle(struct mpd_connection *connection);
/**
* Parses a "changed" pair, which is part of MPD's response to the
* "idle" command.
*
* @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 libmpdclients 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

View File

@ -0,0 +1,84 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
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

View File

@ -0,0 +1,241 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/recv.h>
#include <mpd/compiler.h>
#include <stdbool.h>
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

View File

@ -0,0 +1,96 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
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);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,204 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
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().
*/
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 true if this output is enabled
*/
mpd_pure
bool
mpd_output_get_enabled(const struct mpd_output *output);
/**
* Sends the "outputs" command to MPD. 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);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,49 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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

View File

@ -0,0 +1,181 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef LIBMPDCLIENT_PARSER_H
#define LIBMPDCLIENT_PARSER_H
#include <mpd/protocol.h>
#include <mpd/compiler.h>
#include <stdbool.h>
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

View File

@ -0,0 +1,66 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
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

View File

@ -0,0 +1,242 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
struct mpd_connection;
struct mpd_song;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Fetches the currently selected song (the song referenced by
* status->song and status->songid).
*/
bool
mpd_send_current_song(struct mpd_connection *connection);
/**
* Shortcut for mpd_send_currentsong() 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
*/
bool
mpd_send_play(struct mpd_connection *connection);
bool
mpd_run_play(struct mpd_connection *connection);
/**
* Starts playing the specified song from the beginning.
*
* @param song_pos the position of the song in the queue
* @param connection the connection to MPD
* @return true on success, false on error
*/
bool
mpd_send_play_pos(struct mpd_connection *connection, unsigned song_pos);
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 id the id of the song
* @return true on success, false on error
*/
bool
mpd_send_play_id(struct mpd_connection *connection, unsigned id);
bool
mpd_run_play_id(struct mpd_connection *connection, unsigned song_id);
bool
mpd_send_stop(struct mpd_connection *connection);
bool
mpd_run_stop(struct mpd_connection *connection);
/**
* Toggles the pause mode by sending "pause" without arguments.
*
* @param connection the connection to MPD
*/
bool
mpd_send_toggle_pause(struct mpd_connection *connection);
bool
mpd_run_toggle_pause(struct mpd_connection *connection);
bool
mpd_send_pause(struct mpd_connection *connection, bool mode);
bool
mpd_run_pause(struct mpd_connection *connection, bool mode);
bool
mpd_send_next(struct mpd_connection *connection);
bool
mpd_run_next(struct mpd_connection *connection);
bool
mpd_send_previous(struct mpd_connection *connection);
bool
mpd_run_previous(struct mpd_connection *connection);
/**
* Seeks the specified song.
*
* @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);
bool
mpd_run_seek_pos(struct mpd_connection *connection,
unsigned song_pos, unsigned t);
/**
* Seeks the specified song.
*
* @param connection the connection to MPD
* @param 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 id, unsigned t);
bool
mpd_run_seek_id(struct mpd_connection *connection,
unsigned song_id, unsigned t);
bool
mpd_send_repeat(struct mpd_connection *connection, bool mode);
bool
mpd_run_repeat(struct mpd_connection *connection, bool mode);
bool
mpd_send_random(struct mpd_connection *connection, bool mode);
bool
mpd_run_random(struct mpd_connection *connection, bool mode);
bool
mpd_send_single(struct mpd_connection *connection, bool mode);
bool
mpd_run_single(struct mpd_connection *connection, bool mode);
bool
mpd_send_consume(struct mpd_connection *connection, bool mode);
bool
mpd_run_consume(struct mpd_connection *connection, bool mode);
bool
mpd_send_crossfade(struct mpd_connection *connection, unsigned seconds);
bool
mpd_run_crossfade(struct mpd_connection *connection, unsigned seconds);
/**
* @since libmpdclient 2.2
*/
bool
mpd_send_mixrampdb(struct mpd_connection *connection, float db);
/**
* @since libmpdclient 2.2
*/
bool
mpd_run_mixrampdb(struct mpd_connection *connection, float db);
/**
* @since libmpdclient 2.2
*/
bool
mpd_send_mixrampdelay(struct mpd_connection *connection, float seconds);
/**
* @since libmpdclient 2.2
*/
bool
mpd_run_mixrampdelay(struct mpd_connection *connection, float seconds);
/**
* @since libmpdclient 2.4
*/
bool
mpd_send_clearerror(struct mpd_connection *connection);
/**
* @since libmpdclient 2.4
*/
bool
mpd_run_clearerror(struct mpd_connection *connection);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,216 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
#include <time.h>
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;
#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_entity 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.
*
* @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 a stored playlist.
*
* @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);
/**
* List the content, with full metadata, of a stored playlist.
*
* @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);
bool
mpd_send_playlist_clear(struct mpd_connection *connection, const char *name);
bool
mpd_run_playlist_clear(struct mpd_connection *connection, const char *name);
bool
mpd_send_playlist_add(struct mpd_connection *connection, const char *name,
const char *path);
bool
mpd_run_playlist_add(struct mpd_connection *connection,
const char *name, const char *path);
bool
mpd_send_playlist_move(struct mpd_connection *connection, const char *name,
unsigned from, unsigned to);
bool
mpd_send_playlist_delete(struct mpd_connection *connection, const char *name,
unsigned pos);
bool
mpd_run_playlist_delete(struct mpd_connection *connection,
const char *name, unsigned pos);
bool
mpd_send_save(struct mpd_connection *connection, const char *name);
bool
mpd_run_save(struct mpd_connection *connection, const char *name);
bool
mpd_send_load(struct mpd_connection *connection, const char *name);
bool
mpd_run_load(struct mpd_connection *connection, const char *name);
bool
mpd_send_rename(struct mpd_connection *connection,
const char *from, const char *to);
bool
mpd_run_rename(struct mpd_connection *connection,
const char *from, const char *to);
bool
mpd_send_rm(struct mpd_connection *connection, const char *name);
bool
mpd_run_rm(struct mpd_connection *connection, const char *name);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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

View File

@ -0,0 +1,542 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
struct mpd_connection;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Sends the "playlistinfo" command: list all songs in the queue
* including meta information.
*/
bool
mpd_send_list_queue_meta(struct mpd_connection *connection);
/**
* Like mpd_send_list_queue_meta(), but specifies a (position) range.
*
* @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 "(unsigned)-1" makes the end of the range open
* @return true on success, false on error
*
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
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").
*
* @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").
*
* @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".
*
* @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);
/**
* 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".
*
* @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);
/**
* Receives a response element of mpd_send_queue_changes_brief().
*
* @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.
*/
bool
mpd_send_add(struct mpd_connection *connection, const char *file);
/**
* Shortcut for mpd_send_add() and mpd_response_finish().
*
* @param connection the connection to MPD
* @param uri the URI of the song to be added
* @return true on success, false on error
*/
bool
mpd_run_add(struct mpd_connection *connection, const char *uri);
/**
* Appends a song to the playlist, and returns its id.
*/
bool
mpd_send_add_id(struct mpd_connection *connection, const char *file);
/**
* Inserts a song into the playlist, and returns its id.
*
* @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);
/**
* Returns the id of the new song in the playlist. To be called after
* mpd_send_add_id().
*
* @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.
*
* @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 *file);
/**
* Executes the "addid" command and reads the response.
*
* @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);
/**
* Deletes a song from the queue.
*
* @param connection the connection to MPD
* @param pos the position of the song to be deleted
*/
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 "(unsigned)-1" makes the end of the range open
* @return true on success, false on error
*
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
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 "(unsigned)-1" makes the end of the range open
* @return true on success, false on error
*
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
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
*/
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
*/
bool
mpd_send_shuffle(struct mpd_connection *connection);
/**
* Shortcut for mpd_send_shuffle() and mpd_response_finish().
*
* @param connection the connection to MPD
*/
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 "(unsigned)-1" makes the end of the range open
*
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
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 "(unsigned)-1" makes the end of the range open
*
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
bool
mpd_run_shuffle_range(struct mpd_connection *connection,
unsigned start, unsigned end);
/**
* Clear the queue.
*
* @param connection the connection to MPD
*/
bool
mpd_send_clear(struct mpd_connection *connection);
/**
* Shortcut for mpd_send_clear() and mpd_response_finish().
*
* @param connection the connection to MPD
*/
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
*/
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
*/
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 id
* @param to the new position of the song (not an id!)
*/
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!)
*/
bool
mpd_run_move_id(struct mpd_connection *connection, unsigned from, 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 "(unsigned)-1" 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 "(unsigned)-1"
*/
bool
mpd_send_move_range(struct mpd_connection *connection,
unsigned start, unsigned end, unsigned to);
/**
* Shortcut for mpd_send_move_id() 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 "(unsigned)-1" 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 "(unsigned)-1"
*/
bool
mpd_run_move_range(struct mpd_connection *connection,
unsigned start, unsigned end, unsigned to);
/**
* 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
*/
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
*/
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
*/
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
*/
bool
mpd_run_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2);
/**
* 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
*
* @since libmpdclient 2.6
*/
bool
mpd_send_prio(struct mpd_connection *connection, int 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
*
* @since libmpdclient 2.6
*/
bool
mpd_run_prio(struct mpd_connection *connection, int 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 "(unsigned)-1" makes the end of the range open
*
* @since libmpdclient 2.6
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
bool
mpd_send_prio_range(struct mpd_connection *connection, int 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 "(unsigned)-1" makes the end of the range open
*
* @since libmpdclient 2.6
* @since libmpdclient 2.8 added support for "(unsigned)-1"
*/
bool
mpd_run_prio_range(struct mpd_connection *connection, int 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
*
* @since libmpdclient 2.6
*/
bool
mpd_send_prio_id(struct mpd_connection *connection, int 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
*
* @since libmpdclient 2.6
*/
bool
mpd_run_prio_id(struct mpd_connection *connection, int priority,
unsigned id);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,88 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
struct mpd_pair;
struct mpd_connection;
#ifdef __cplusplus
extern "C" {
#endif
/**
* 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

View File

@ -0,0 +1,72 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
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

View File

@ -0,0 +1,254 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 MPD_DB_H
#define MPD_DB_H
#include <mpd/connection.h>
#include <mpd/tag.h>
#include <mpd/compiler.h>
#include <stdbool.h>
#include <time.h>
/**
* 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 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);
/**
* 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);
/**
* Request only a portion of the result set.
*
* @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
*
* @since libmpdclient 2.10
*/
bool
mpd_search_add_window(struct mpd_connection *connection,
unsigned start, unsigned end);
/**
* 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

View File

@ -0,0 +1,64 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
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

View File

@ -0,0 +1,123 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <stdbool.h>
/**
* \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

View File

@ -0,0 +1,222 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/tag.h>
#include <mpd/compiler.h>
#include <stdbool.h>
#include <time.h>
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. Zero 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);
/**
* 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);
/**
* 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

View File

@ -0,0 +1,163 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
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.
*
* @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 *status, 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

View File

@ -0,0 +1,309 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
/**
* 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,
};
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 true if single mode is on.
*/
mpd_pure
bool
mpd_status_get_single(const struct mpd_status *status);
/**
* Returns true if consume mode is on.
*/
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.
*
* @since libmpdclient 2.2
*/
mpd_pure
float
mpd_status_get_mixrampdb(const struct mpd_status *status);
/**
* Returns mixrampdelay setting in seconds. Negative means mixramp 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 PLAY or 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_next_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);
/**
* 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 error message
*/
mpd_pure
const char *
mpd_status_get_error(const struct mpd_status *status);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,200 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
#include <stddef.h>
struct mpd_connection;
#ifdef __cplusplus
extern "C" {
#endif
/**
* 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);
/**
* 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.
*
* @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);
#ifdef __cplusplus
}
#endif
#endif /* MPD_STICKER_H */

View File

@ -0,0 +1,106 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#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 and #MPD_TAG_ALBUM_ARTIST_SORT.
*/
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_ARTIST_SORT,
MPD_TAG_ALBUM,
MPD_TAG_ALBUM_ARTIST,
MPD_TAG_ALBUM_ARTIST_SORT,
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_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

View File

@ -0,0 +1,58 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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

View File

@ -0,0 +1,372 @@
libmpdclient2 {
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/capabilities.h */
mpd_send_allowed_commands;
mpd_send_disallowed_commands;
mpd_send_list_url_schemes;
mpd_send_list_tag_types;
/* 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_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/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/output.h */
mpd_output_begin;
mpd_output_feed;
mpd_output_free;
mpd_output_get_id;
mpd_output_get_name;
mpd_output_get_enabled;
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/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_repeat;
mpd_run_repeat;
mpd_send_random;
mpd_run_random;
mpd_send_single;
mpd_run_single;
mpd_send_consume;
mpd_run_consume;
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_meta;
mpd_send_playlist_clear;
mpd_run_playlist_clear;
mpd_send_playlist_add;
mpd_run_playlist_add;
mpd_send_playlist_move;
mpd_send_playlist_delete;
mpd_run_playlist_delete;
mpd_send_save;
mpd_run_save;
mpd_send_load;
mpd_run_load;
mpd_send_rename;
mpd_run_rename;
mpd_send_rm;
mpd_run_rm;
/* 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_brief;
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_prio;
mpd_run_prio;
mpd_send_prio_range;
mpd_run_prio_range;
mpd_send_prio_id;
mpd_run_prio_id;
/* mpd/recv.h */
mpd_recv_pair;
mpd_recv_pair_named;
mpd_return_pair;
mpd_enqueue_pair;
/* mpd/response.h */
mpd_response_finish;
mpd_response_next;
/* mpd/search.h */
mpd_search_db_songs;
mpd_search_add_db_songs;
mpd_search_queue_songs;
mpd_search_db_tags;
mpd_count_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_window;
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_set_pos;
mpd_song_get_pos;
mpd_song_get_id;
mpd_song_get_prio;
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;
mpd_status_get_consume;
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_error;
/* 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/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;
local:
*;
};

View File

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libmpdclient
Description: Music Player Daemon client library
Version: @VERSION@
Libs: -L${libdir} -lmpdclient
Cflags: -I${includedir}

View File

@ -0,0 +1,74 @@
# ===========================================================================
# http://www.nongnu.org/autoconf-archive/ax_check_compiler_flags.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE])
#
# DESCRIPTION
#
# Check whether the given compiler FLAGS work with the current language's
# compiler, or whether they give an error. (Warnings, however, are
# ignored.)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# LICENSE
#
# Copyright (c) 2009 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2009 Matteo Frigo
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
AS_LITERAL_IF([$1],
[AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1]), [
ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
[ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])
AC_MSG_RESULT($ax_check_compiler_flags)
if test "x$ax_check_compiler_flags" = xyes; then
m4_default([$2], :)
else
m4_default([$3], :)
fi
])dnl AX_CHECK_COMPILER_FLAGS

View File

@ -0,0 +1,391 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "iasync.h"
#include "buffer.h"
#include "ierror.h"
#include "quote.h"
#include "socket.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#ifndef WIN32
#include <sys/socket.h>
static inline int
closesocket(int fd)
{
return close(fd);
}
#endif
#ifndef MSG_DONTWAIT
#define MSG_DONTWAIT 0
#endif
struct mpd_async {
int 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 >= 0);
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);
closesocket(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);
}
int
mpd_async_get_fd(const struct mpd_async *async)
{
assert(async != NULL);
assert(async->fd >= 0);
return async->fd;
}
void
mpd_async_set_keepalive(struct mpd_async *async,
bool keepalive)
{
assert(async != NULL);
assert(async->fd >= 0);
mpd_socket_keepalive(async->fd, keepalive);
}
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
ignore_errno(int e)
{
#ifdef WIN32
return e == WSAEINTR || e == WSAEINPROGRESS;
#else
return e == EINTR || e == EAGAIN;
#endif
}
static bool
mpd_async_read(struct mpd_async *async)
{
size_t room;
ssize_t nbytes;
assert(async != NULL);
assert(async->fd >= 0);
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 (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 >= 0);
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 (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;
}

View File

@ -0,0 +1,157 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_BUFFER_H
#define MPD_BUFFER_H
#include <assert.h>
#include <string.h>
#include <stdbool.h>
/**
* 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 += 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 += nbytes;
}
#endif

View File

@ -0,0 +1,57 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/capabilities.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include <stddef.h>
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);
}

View File

@ -0,0 +1,134 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/message.h>
#include <mpd/send.h>
#include <mpd/response.h>
#include "internal.h"
#include "run.h"
#include <assert.h>
#include <stddef.h>
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);
}

View File

@ -0,0 +1,301 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/connection.h>
#include <mpd/settings.h>
#include <mpd/async.h>
#include <mpd/parser.h>
#include <mpd/password.h>
#include "resolver.h"
#include "sync.h"
#include "socket.h"
#include "internal.h"
#include "iasync.h"
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#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))) {
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 *settings =
mpd_settings_new(host, port, timeout_ms, NULL, NULL);
if (settings == NULL)
return NULL;
struct mpd_connection *connection = malloc(sizeof(*connection));
if (connection == NULL) {
mpd_settings_free(settings);
return NULL;
}
connection->settings = settings;
bool success;
int 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));
host = mpd_settings_get_host(settings);
fd = mpd_socket_connect(host, mpd_settings_get_port(settings),
&connection->timeout, &connection->error);
if (fd < 0) {
#if defined(DEFAULT_SOCKET) && defined(ENABLE_TCP)
if (host == NULL || strcmp(host, DEFAULT_SOCKET) == 0) {
/* special case: try the default host if the
default socket failed */
mpd_settings_free(settings);
settings = mpd_settings_new(DEFAULT_HOST, DEFAULT_PORT,
timeout_ms, NULL, NULL);
connection->settings = settings;
mpd_error_clear(&connection->error);
fd = mpd_socket_connect(DEFAULT_HOST, DEFAULT_PORT,
&connection->timeout,
&connection->error);
}
#endif
if (fd < 0)
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->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->settings != NULL)
mpd_settings_free(connection->settings);
free(connection);
}
void
mpd_connection_set_keepalive(struct mpd_connection *connection,
bool keepalive)
{
assert(connection != NULL);
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;
}

View File

@ -0,0 +1,115 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/output.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include <mpd/response.h>
#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_int_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_int_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_int_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);
}

View File

@ -0,0 +1,179 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/playlist.h>
#include <mpd/send.h>
#include <mpd/response.h>
#include "run.h"
#include <limits.h>
#include <stdio.h>
/* (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_meta(struct mpd_connection *connection, const char *name)
{
return mpd_send_command(connection, "listplaylistinfo", name, NULL);
}
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_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_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_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);
}
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_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);
}

View File

@ -0,0 +1,88 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*
* mpd_connection specific functions declared in mpd/stats.h.
*
*/
#include <mpd/stats.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include "internal.h"
#include <assert.h>
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;
}

View File

@ -0,0 +1,80 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*
* mpd_connection specific functions declared in mpd/status.h.
*
*/
#include <mpd/status.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#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;
}

View File

@ -0,0 +1,114 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/database.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include <mpd/pair.h>
#include <mpd/response.h>
#include "run.h"
#include <stddef.h>
#include <stdlib.h>
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_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;
int ret = 0;
pair = mpd_recv_pair_named(connection, "updating_db");
if (pair != NULL) {
ret = atoi(pair->value);
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;
}

View File

@ -0,0 +1,152 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/directory.h>
#include <mpd/pair.h>
#include "uri.h"
#include "iso8601.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
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;
}

View File

@ -0,0 +1,237 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/entity.h>
#include <mpd/playlist.h>
#include "internal.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
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;
}

View File

@ -0,0 +1,79 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/connection.h>
#include "internal.h"
#include <assert.h>
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;
}

View File

@ -0,0 +1,285 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/client.h>
#include <mpd/status.h>
#include <mpd/entity.h>
#include <mpd/search.h>
#include <mpd/tag.h>
#include <mpd/message.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
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);
}
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);
{
int i;
for(i=0;i<3;i++) {
printf("version[%i]: %i\n",i,
mpd_connection_get_server_version(conn)[i]);
}
}
if(argc==1) {
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==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);
}
mpd_connection_free(conn);
return 0;
}

View File

@ -0,0 +1,119 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*
* 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 <assert.h>
#include <stdbool.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#endif
#ifndef WIN32
static int
fd_mask_flags(int fd, int and_mask, int xor_mask)
{
int ret;
assert(fd >= 0);
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(int 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(int fd)
{
#ifdef WIN32
u_long val = 1;
return ioctlsocket(fd, FIONBIO, &val);
#else
int flags;
assert(fd >= 0);
flags = fcntl(fd, F_GETFL);
if (flags < 0)
return flags;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#endif
}
int
socket_cloexec_nonblock(int domain, int type, int protocol)
{
int fd;
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
fd = socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
if (fd >= 0 || errno != EINVAL)
return fd;
#endif
fd = socket(domain, type, protocol);
if (fd >= 0) {
fd_set_cloexec(fd, true);
fd_set_nonblock(fd);
}
return fd;
}

View File

@ -0,0 +1,46 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*
* 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
/**
* Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag
* (atomically if supported by the OS).
*/
int
socket_cloexec_nonblock(int domain, int type, int protocol);
#endif

View File

@ -0,0 +1,47 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_IASYNC_H
#define MPD_IASYNC_H
#include <mpd/async.h>
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);
#endif

View File

@ -0,0 +1,230 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/idle.h>
#include <mpd/send.h>
#include <mpd/connection.h>
#include <mpd/pair.h>
#include <mpd/recv.h>
#include <mpd/response.h>
#include "internal.h"
#include "isend.h"
#include "run.h"
#include <string.h>
static const char *const idle_names[] = {
"database",
"stored_playlist",
"playlist",
"player",
"mixer",
"output",
"options",
"update",
"sticker",
"subscription",
"message",
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;
}

View File

@ -0,0 +1,152 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in so and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "ierror.h"
#include "socket.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
void
mpd_error_deinit(struct mpd_error_info *error)
{
assert(error != NULL);
if (error->code != MPD_ERROR_SUCCESS && error->message != NULL)
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 = FormatMessage(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;
}

View File

@ -0,0 +1,225 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_IERROR_H
#define MPD_IERROR_H
#include <mpd/error.h>
#include <mpd/protocol.h>
#include <mpd/compiler.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
/**
* 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.
*/
int 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, int 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

View File

@ -0,0 +1,164 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_INTERNAL_H
#define MPD_INTERNAL_H
#include <mpd/pair.h>
#include "ierror.h"
#include <sys/time.h>
/**
* This opaque object represents a connection to a MPD server. Call
* mpd_connection_new() to create a new instance.
*/
struct mpd_connection {
/**
* The connection settings.
*/
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;
}
#endif

View File

@ -0,0 +1,91 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_ISEND_H
#define MPD_ISEND_H
#include <stdbool.h>
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_s_u_command(struct mpd_connection *connection, const char *command,
const char *arg1, unsigned arg2);
bool
mpd_send_range_command(struct mpd_connection *connection, const char *command,
unsigned arg1, unsigned arg2);
/**
* 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);
bool
mpd_send_range_u_command(struct mpd_connection *connection,
const char *command,
unsigned start, unsigned end, unsigned arg2);
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

View File

@ -0,0 +1,154 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "iso8601.h"
#include <stdio.h>
#include <stdlib.h>
#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;
unsigned year, month, day, hour, minute, second;
struct tm tm;
year = strtoul(input, &endptr, 10);
if (year < 1970 || year >= 3000 || *endptr != '-')
/* beware of the Y3K problem! */
return 0;
input = endptr + 1;
month = strtoul(input, &endptr, 10);
if (month < 1 || month > 12 || *endptr != '-')
return 0;
input = endptr + 1;
day = strtoul(input, &endptr, 10);
if (day < 1 || day > 31 || *endptr != 'T')
return 0;
input = endptr + 1;
hour = strtoul(input, &endptr, 10);
if (endptr == input || hour >= 24 || *endptr != ':')
return 0;
input = endptr + 1;
minute = strtoul(input, &endptr, 10);
if (endptr == input || minute >= 60 || *endptr != ':')
return 0;
input = endptr + 1;
second = strtoul(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;
}

View File

@ -0,0 +1,56 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_ISO8601_H
#define MPD_ISO8601_H
#include <stdbool.h>
#include <time.h>
/**
* 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

View File

@ -0,0 +1,91 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/list.h>
#include <mpd/send.h>
#include "internal.h"
#include "isend.h"
#include <assert.h>
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);
connection->sending_command_list = true;
if (!success)
return false;
assert(connection->receiving);
return true;
}

View File

@ -0,0 +1,103 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/message.h>
#include <mpd/pair.h>
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
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) {
if (output->text != NULL)
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;
}

View File

@ -0,0 +1,62 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/mixer.h>
#include <mpd/send.h>
#include <mpd/response.h>
#include "isend.h"
#include "run.h"
bool
mpd_send_set_volume(struct mpd_connection *connection, unsigned volume)
{
return mpd_send_int_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);
}

View File

@ -0,0 +1,117 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/output.h>
#include <mpd/pair.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
struct mpd_output {
unsigned id;
char *name;
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 = atoi(pair->value);
output->name = NULL;
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) {
if (output->name != NULL)
free(output->name);
output->name = strdup(pair->value);
} else if (strcmp(pair->name, "outputenabled") == 0)
output->enabled = atoi(pair->value) != 0;
return true;
}
void
mpd_output_free(struct mpd_output *output)
{
assert(output != NULL);
if (output->name != NULL)
free(output->name);
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;
}
bool
mpd_output_get_enabled(const struct mpd_output *output)
{
assert(output != NULL);
return output->enabled;
}

View File

@ -0,0 +1,207 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/parser.h>
#include <mpd/protocol.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
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 = strtol(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;
}

View File

@ -0,0 +1,49 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/password.h>
#include <mpd/send.h>
#include <mpd/response.h>
#include "run.h"
#include <stddef.h>
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);
}

View File

@ -0,0 +1,312 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/player.h>
#include <mpd/send.h>
#include <mpd/song.h>
#include <mpd/response.h>
#include "isend.h"
#include "run.h"
#include <limits.h>
#include <stdio.h>
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_int_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 id)
{
return mpd_send_int_command(connection, "playid", 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_int2_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 id, unsigned t)
{
return mpd_send_int2_command(connection, "seekid", 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_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(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(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_int_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);
}

View File

@ -0,0 +1,144 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/playlist.h>
#include <mpd/pair.h>
#include "iso8601.h"
#include "uri.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
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;
}

View File

@ -0,0 +1,436 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/queue.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include <mpd/pair.h>
#include <mpd/response.h>
#include <mpd/song.h>
#include "internal.h"
#include "isend.h"
#include "run.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
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_int_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_int_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_ll_command(connection, "plchanges", version);
}
bool
mpd_send_queue_changes_brief(struct mpd_connection *connection,
unsigned version)
{
return mpd_send_ll_command(connection, "plchangesposid", version);
}
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 = atoi(pair->value);
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 = atoi(pair->value);
mpd_return_pair(connection, pair);
return !mpd_error_is_defined(&connection->error);
}
bool
mpd_send_add(struct mpd_connection *connection, const char *file)
{
return mpd_send_command(connection, "add", file, 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_id(struct mpd_connection *connection, const char *file)
{
return mpd_send_command(connection, "addid", file, 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);
}
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 *file)
{
int id;
if (!mpd_run_check(connection) ||
!mpd_send_add_id(connection, file))
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;
}
bool
mpd_send_delete(struct mpd_connection *connection, unsigned pos)
{
return mpd_send_int_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_int_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_int2_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_id(struct mpd_connection *connection, unsigned from, unsigned to)
{
return mpd_send_int2_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_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_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2)
{
return mpd_send_int2_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_int2_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_prio(struct mpd_connection *connection, int priority,
unsigned position)
{
return mpd_send_int2_command(connection, "prio", priority, position);
}
bool
mpd_run_prio(struct mpd_connection *connection, int 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, int priority,
unsigned start, unsigned end)
{
return mpd_send_i_range_command(connection, "prio", priority,
start, end);
}
bool
mpd_run_prio_range(struct mpd_connection *connection, int 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, int priority,
unsigned id)
{
return mpd_send_int2_command(connection, "prioid", priority, id);
}
bool
mpd_run_prio_id(struct mpd_connection *connection, int priority,
unsigned id)
{
return mpd_run_check(connection) &&
mpd_send_prio_id(connection, priority, id) &&
mpd_response_finish(connection);
}

View File

@ -0,0 +1,74 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "quote.h"
#include <stddef.h>
/**
* 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;
}

View File

@ -0,0 +1,44 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#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

View File

@ -0,0 +1,67 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/directory.h>
#include <mpd/recv.h>
#include "internal.h"
#include <errno.h>
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;
}

View File

@ -0,0 +1,200 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/recv.h>
#include <mpd/pair.h>
#include <mpd/parser.h>
#include "internal.h"
#include "iasync.h"
#include "sync.h"
#include <string.h>
#include <stdlib.h>
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;
}
}

View File

@ -0,0 +1,200 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "resolver.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <sys/socket.h>
# include <sys/un.h>
#ifdef ENABLE_TCP
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
#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
size_t path_length = strlen(host);
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 + 1);
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);
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
}

View File

@ -0,0 +1,52 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef LIBMPDCLIENT_RESOLVER_H
#define LIBMPDCLIENT_RESOLVER_H
#include <stddef.h>
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

View File

@ -0,0 +1,111 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/response.h>
#include <mpd/recv.h>
#include "internal.h"
#include <assert.h>
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;
}

View File

@ -0,0 +1,67 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/playlist.h>
#include <mpd/recv.h>
#include "internal.h"
#include <errno.h>
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;
}

View File

@ -0,0 +1,53 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "run.h"
#include <mpd/response.h>
#include <mpd/status.h>
#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;
}

View File

@ -0,0 +1,47 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_RUN_H
#define MPD_RUN_H
#include <stdbool.h>
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

View File

@ -0,0 +1,352 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/search.h>
#include <mpd/send.h>
#include <mpd/pair.h>
#include <mpd/recv.h>
#include "internal.h"
#include "iso8601.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static bool
mpd_search_init(struct mpd_connection *connection, const char *cmd)
{
assert(connection != NULL);
assert(cmd != 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;
}
connection->request = strdup(cmd);
if (connection->request == NULL) {
mpd_error_code(&connection->error, MPD_ERROR_OOM);
return false;
}
return true;
}
bool
mpd_search_db_songs(struct mpd_connection *connection, bool exact)
{
return mpd_search_init(connection,
exact ? "find" : "search");
}
bool
mpd_search_add_db_songs(struct mpd_connection *connection, bool exact)
{
return mpd_search_init(connection,
exact ? "findadd" : "searchadd");
}
bool
mpd_search_queue_songs(struct mpd_connection *connection, bool exact)
{
return mpd_search_init(connection,
exact ? "playlistfind" : "playlistsearch");
}
bool
mpd_search_db_tags(struct mpd_connection *connection, enum mpd_tag_type type)
{
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;
}
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);
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;
}
connection->request = strdup("count");
if (connection->request == NULL) {
mpd_error_code(&connection->error, MPD_ERROR_OOM);
return false;
}
return true;
}
static char *
mpd_search_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;
}
static 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;
}
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_search_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_window(struct mpd_connection *connection,
unsigned start, unsigned end)
{
assert(connection != NULL);
assert(start <= end);
const size_t size = 64;
char *dest = mpd_search_prepare_append(connection, size);
if (dest == NULL)
return false;
snprintf(dest, size, " window %u:%u", start, end);
return true;
}
bool
mpd_search_commit(struct mpd_connection *connection)
{
assert(connection != NULL);
if (mpd_error_is_defined(&connection->error)) {
mpd_search_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_search_cancel(struct mpd_connection *connection)
{
assert(connection != NULL);
if (connection->request != NULL) {
free(connection->request);
connection->request = NULL;
}
}
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);
}

View File

@ -0,0 +1,247 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/send.h>
#include "isend.h"
#include "internal.h"
#include "sync.h"
#include <stdarg.h>
#include <limits.h>
#include <stdio.h>
/* (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,
};
static void
format_range(char *buffer, size_t size, unsigned start, unsigned end)
{
if (end == (unsigned)-1)
/* the special value -1 means "open end" */
snprintf(buffer, size, "%u:", start);
else
snprintf(buffer, size, "%u:%u", start, end);
}
/**
* 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)
{
char arg_string[INTLEN];
snprintf(arg_string, sizeof(arg_string), "%f", arg);
return mpd_send_command(connection, command, arg_string, 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_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_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_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_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;
}

View File

@ -0,0 +1,204 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/settings.h>
#include "config.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
struct mpd_settings {
char *host;
unsigned port, timeout_ms;
char *password;
};
/**
* Parses the password from the host specification in the form
* "password@hostname".
*
* @param host_p a pointer to the "host" variable, which may be
* modified by this function
* @return an allocated password string, or NULL if there was no
* password
*/
static const char *
mpd_parse_host_password(const char *host, char **password_r)
{
const char *at;
char *password;
assert(password_r != NULL);
assert(*password_r == NULL);
if (host == NULL ||
/* if the MPD_HOST begins with a '@' then it's not an
empty password but an abstract socket */
*host == '@')
return host;
at = strchr(host, '@');
if (at == NULL)
return host;
password = malloc(at - host + 1);
if (password != NULL) {
/* silently ignoring out-of-memory */
memcpy(password, host, at - host);
password[at - host] = 0;
*password_r = password;
}
return at + 1;
}
/**
* Parses the host specification. If not specified, it attempts to
* load it from the environment variable MPD_HOST.
*/
static const char *
mpd_check_host(const char *host, char **password_r)
{
assert(password_r != NULL);
assert(*password_r == NULL);
if (host == NULL)
host = getenv("MPD_HOST");
if (host != NULL)
host = mpd_parse_host_password(host, password_r);
return host;
}
/**
* 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 = atoi(env_port);
}
return port;
}
static unsigned
mpd_default_timeout_ms(void)
{
const char *timeout_string = getenv("MPD_TIMEOUT");
if (timeout_string != NULL) {
int timeout_s = atoi(timeout_string);
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->password = NULL;
port = mpd_check_port(port);
host = mpd_check_host(host, &settings->password);
if (settings->password == NULL && password != NULL)
settings->password = strdup(password);
if (host == NULL) {
#ifdef DEFAULT_SOCKET
if (port == 0)
/* default to local socket only if no port was
explicitly configured */
host = DEFAULT_SOCKET;
else
#endif
host = DEFAULT_HOST;
}
settings->host = strdup(host);
settings->timeout_ms = timeout_ms != 0
? timeout_ms
: mpd_default_timeout_ms();
settings->port = host[0] == '/'
? 0 /* no port for local socket */
: (port != 0 ? port : DEFAULT_PORT);
return settings;
}
void
mpd_settings_free(struct mpd_settings *settings)
{
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;
}

View File

@ -0,0 +1,219 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "socket.h"
#include "fd_util.h"
#include "resolver.h"
#include "ierror.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/select.h>
# include <sys/socket.h>
# include <netdb.h>
# include <sys/un.h>
# include <errno.h>
#endif
#ifndef MSG_DONTWAIT
# define MSG_DONTWAIT 0
#endif
static bool
ignore_errno(int e)
{
#ifdef WIN32
return e == WSAEINTR || e == WSAEINPROGRESS || e == WSAEWOULDBLOCK;
#else
return e == EINTR || e == EINPROGRESS;
#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 readable.
*/
static int
mpd_socket_wait(unsigned fd, struct timeval *tv)
{
fd_set fds;
int ret;
while (1) {
FD_ZERO(&fds);
FD_SET(fd, &fds);
ret = select(fd + 1, NULL, &fds, &fds, tv);
if (ret > 0)
return 0;
if (ret == 0 || !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(int fd, struct timeval *tv)
{
int ret;
int s_err = 0;
socklen_t s_err_size = sizeof(s_err);
ret = mpd_socket_wait(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;
}
int
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 fd, 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) {
fd = socket_cloexec_nonblock(address->family, SOCK_STREAM,
address->protocol);
if (fd < 0) {
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 (!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(int fd)
{
#ifndef WIN32
return close(fd);
#else
return closesocket(fd);
#endif
}
void
mpd_socket_keepalive(int fd, bool keepalive)
{
int keepalive_i = keepalive;
(void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
(const char *) &keepalive_i, sizeof keepalive_i);
}

View File

@ -0,0 +1,87 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#ifndef MPD_SOCKET_H
#define MPD_SOCKET_H
#include <stdbool.h>
#ifdef WIN32
# include <winsock2.h>
#else
# include <errno.h>
#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
}
/**
* Connects the socket to the specified host and port.
*
* @return the socket file descriptor, or -1 on failure
*/
int
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(int fd);
/**
* Sets (or unsets) keepalive on a socket descriptor.
*/
void
mpd_socket_keepalive(int fd, bool keepalive);
#endif

View File

@ -0,0 +1,533 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/song.h>
#include <mpd/pair.h>
#include <mpd/recv.h>
#include "internal.h"
#include "iso8601.h"
#include "uri.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
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 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
};
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->pos = 0;
song->id = 0;
song->prio = 0;
#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, 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->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)
{
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 NULL;
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)
{
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)
{
return song->duration_ms > 0
? song->duration_ms
: (song->duration * 1000u);
}
unsigned
mpd_song_get_start(const struct mpd_song *song)
{
return song->start;
}
unsigned
mpd_song_get_end(const struct mpd_song *song)
{
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)
{
return song->last_modified;
}
void
mpd_song_set_pos(struct mpd_song *song, unsigned pos)
{
song->pos = pos;
}
unsigned
mpd_song_get_pos(const struct mpd_song *song)
{
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)
{
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)
{
return song->prio;
}
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;
}
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, atoi(pair->value));
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, "Pos") == 0)
mpd_song_set_pos(song, atoi(pair->value));
else if (strcmp(pair->name, "Id") == 0)
mpd_song_set_id(song, atoi(pair->value));
else if (strcmp(pair->name, "Prio") == 0)
mpd_song_set_prio(song, atoi(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;
}

View File

@ -0,0 +1,143 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/stats.h>
#include <mpd/pair.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
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 = atoi(pair->value);
else if (strcmp(pair->name, "albums") == 0)
stats->number_of_albums = atoi(pair->value);
else if (strcmp(pair->name, "songs") == 0)
stats->number_of_songs = atoi(pair->value);
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;
}

View File

@ -0,0 +1,427 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Music Player Daemon 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 FOUNDATION 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.
*/
#include <mpd/status.h>
#include <mpd/pair.h>
#include <mpd/audio_format.h>
#include <stdlib.h>
#include <string.h>
/**
* 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? */
bool single;
/** Song consume mode enabled? */
bool 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;
/** 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 = false;
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->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;
}
static void
parse_audio_format(struct mpd_audio_format *audio_format, const char *p)
{
char *endptr;
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 = strtoul(p, &endptr, 10);
p = *endptr == ':' ? endptr + 1 : NULL;
}
audio_format->channels = p != NULL
? strtoul(p, NULL, 10)
: 0;
} else {
audio_format->bits = 0;
audio_format->channels = 0;
}
}
void
mpd_status_feed(struct mpd_status *status, const struct mpd_pair *pair)
{
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 = !!atoi(pair->value);
else if (strcmp(pair->name, "consume") == 0)
status->consume = !!atoi(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 = atoi(pair->value);
else if (strcmp(pair->name, "bitrate") == 0)
status->kbit_rate = atoi(pair->value);
else if (strcmp(pair->name, "state") == 0)
status->state = parse_mpd_state(pair->value);
else if (strcmp(pair->name, "song") == 0)
status->song_pos = atoi(pair->value);
else if (strcmp(pair->name, "songid") == 0)
status->song_id = atoi(pair->value);
else if (strcmp(pair->name, "nextsong") == 0)
status->next_song_pos = atoi(pair->value);
else if (strcmp(pair->name, "nextsongid") == 0)
status->next_song_id = atoi(pair->value);
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, "error") == 0) {
if (status->error != NULL)
free(status->error);
status->error = strdup(pair->value);
} else if (strcmp(pair->name, "xfade") == 0)
status->crossfade = atoi(pair->value);
else if (strcmp(pair->name, "mixrampdb") == 0)
status->mixrampdb = atof(pair->value);
else if (strcmp(pair->name, "mixrampdelay") == 0)
status->mixrampdelay = atof(pair->value);
else if (strcmp(pair->name, "updating_db") == 0)
status->update_id = atoi(pair->value);
else if (strcmp(pair->name, "audio") == 0)
parse_audio_format(&status->audio_format, pair->value);
}
void mpd_status_free(struct mpd_status * status) {
if (status->error) free(status->error);
free(status);
}
int mpd_status_get_volume(const struct mpd_status *status)
{
return status->volume;
}
bool
mpd_status_get_repeat(const struct mpd_status *status)
{
return status->repeat;
}
bool
mpd_status_get_random(const struct mpd_status *status)
{
return status->random;
}
bool
mpd_status_get_single(const struct mpd_status *status)
{
return status->single;
}
bool
mpd_status_get_consume(const struct mpd_status *status)
{
return status->consume;
}
unsigned
mpd_status_get_queue_length(const struct mpd_status *status)
{
return status->queue_length;
}
unsigned
mpd_status_get_queue_version(const struct mpd_status *status)
{
return status->queue_version;
}
enum mpd_state
mpd_status_get_state(const struct mpd_status *status)
{
return status->state;
}
unsigned
mpd_status_get_crossfade(const struct mpd_status *status)
{
return status->crossfade;
}
float
mpd_status_get_mixrampdb(const struct mpd_status *status)
{
return status->mixrampdb;
}
float
mpd_status_get_mixrampdelay(const struct mpd_status *status)
{
return status->mixrampdelay;
}
int
mpd_status_get_song_pos(const struct mpd_status *status)
{
return status->song_pos;
}
int
mpd_status_get_song_id(const struct mpd_status *status)
{
return status->song_id;
}
int
mpd_status_get_next_song_pos(const struct mpd_status *status)
{
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)
{
return status->elapsed_time;
}
unsigned
mpd_status_get_elapsed_ms(const struct mpd_status *status)
{
return status->elapsed_ms;
}
unsigned
mpd_status_get_total_time(const struct mpd_status *status)
{
return status->total_time;
}
unsigned
mpd_status_get_kbit_rate(const struct mpd_status *status)
{
return status->kbit_rate;
}
const struct mpd_audio_format *
mpd_status_get_audio_format(const struct mpd_status *status)
{
return status->audio_format.sample_rate > 0 ||
status->audio_format.bits > 0 ||
status->audio_format.channels > 0
? &status->audio_format
: NULL;
}
unsigned
mpd_status_get_update_id(const struct mpd_status *status)
{
return status->update_id;
}
const char *
mpd_status_get_error(const struct mpd_status *status)
{
return status->error;
}

View File

@ -0,0 +1,162 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include <mpd/sticker.h>
#include <mpd/connection.h>
#include <mpd/send.h>
#include <mpd/recv.h>
#include <mpd/pair.h>
#include <mpd/response.h>
#include "run.h"
#include <assert.h>
#include <string.h>
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_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);
}

View File

@ -0,0 +1,193 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
#include "sync.h"
#include "socket.h"
#include <mpd/async.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef WIN32
#include <sys/select.h>
#endif
#include <fcntl.h>
#include <unistd.h>
static bool
ignore_errno(int e)
{
#ifdef WIN32
return e == WSAEINTR || e == WSAEINPROGRESS;
#else
return e == EINTR;
#endif
}
static enum mpd_async_event
mpd_sync_poll(struct mpd_async *async, struct timeval *tv)
{
unsigned 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 || !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;
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;
}
}

View File

@ -0,0 +1,74 @@
/* libmpdclient
(c) 2003-2015 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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 FOUNDATION 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.
*/
/*! \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 <mpd/compiler.h>
#include <stdbool.h>
#include <stdarg.h>
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);
#endif

Some files were not shown because too many files have changed in this diff Show More