aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-01-19 19:09:49 +0100
committerMax Kellermann <max@duempel.org>2009-01-19 19:09:49 +0100
commitf9c693e602231e77eee94580addf60eff095b2de (patch)
treea7179381c68640f730f82b410f96a6ac54e1009b
parent2934585d5ae3d7b74e4bec099711d6e75271cc35 (diff)
downloadmpd-f9c693e602231e77eee94580addf60eff095b2de.tar.gz
mpd-f9c693e602231e77eee94580addf60eff095b2de.tar.xz
mpd-f9c693e602231e77eee94580addf60eff095b2de.zip
command: added "sticker" command
The "sticker" command allows clients to query or manipulate the sticker database. This patch implements the sub-commands "get" and "set"; more will follow soon (enumeration), as well as extended "lsinfo" / "playlistinfo" versions.
-rw-r--r--doc/protocol.xml67
-rw-r--r--src/command.c72
2 files changed, 139 insertions, 0 deletions
diff --git a/doc/protocol.xml b/doc/protocol.xml
index ff5d4838f..36ee3c35d 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -1156,6 +1156,73 @@ OK
</section>
<section>
+ <title>Stickers</title>
+
+ <para>
+ "Stickers" are pieces of information attached to existing MPD
+ objects (e.g. song files, directories, albums). Clients can
+ create arbitrary name/value pairs. MPD itself does not assume
+ any special meaning in them.
+ </para>
+
+ <para>
+ The goal is to allow clients to share additional (possibly
+ dynamic) information about songs, which is neither stored on
+ the client (not available to other clients), nor stored in the
+ song files (MPD has no write access).
+ </para>
+
+ <para>
+ Client developers should create a standard for common sticker
+ names, to ensure interoperability.
+ </para>
+
+ <para>
+ Objects which may have stickers are addressed by their object
+ type ("song" for song objects) and their URI (the path within
+ the database for songs).
+ </para>
+
+ <variablelist>
+ <varlistentry id="command_sticker_get">
+ <term>
+ <cmdsynopsis>
+ <command>sticker</command>
+ <arg choice="plain">get</arg>
+ <arg choice="req"><replaceable>TYPE</replaceable></arg>
+ <arg choice="req"><replaceable>URI</replaceable></arg>
+ <arg choice="req"><replaceable>NAME</replaceable></arg>
+ </cmdsynopsis>
+ </term>
+ <listitem>
+ <para>
+ Reads a sticker value for the specified object.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry id="command_sticker_set">
+ <term>
+ <cmdsynopsis>
+ <command>sticker</command>
+ <arg choice="plain">set</arg>
+ <arg choice="req"><replaceable>TYPE</replaceable></arg>
+ <arg choice="req"><replaceable>URI</replaceable></arg>
+ <arg choice="req"><replaceable>NAME</replaceable></arg>
+ <arg choice="req"><replaceable>VALUE</replaceable></arg>
+ </cmdsynopsis>
+ </term>
+ <listitem>
+ <para>
+ Adds a sticker value to the specified object. If a
+ sticker item with that name already exists, it is
+ replaced.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section>
<title>Connection settings</title>
<variablelist>
diff --git a/src/command.c b/src/command.c
index dbc7bdb99..6e8dc9fc0 100644
--- a/src/command.c
+++ b/src/command.c
@@ -40,6 +40,11 @@
#include "idle.h"
#include "config.h"
+#ifdef ENABLE_SQLITE
+#include "sticker.h"
+#include "song_sticker.h"
+#endif
+
#include <assert.h>
#include <time.h>
#include <stdlib.h>
@@ -1403,6 +1408,70 @@ handle_idle(struct client *client,
return 1;
}
+#ifdef ENABLE_SQLITE
+static enum command_return
+handle_sticker_song(struct client *client, int argc, char *argv[])
+{
+ struct song *song = db_get_song(argv[3]);
+
+ if (song == NULL) {
+ command_error(client, ACK_ERROR_NO_EXIST,
+ "no such song");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ if (argc == 5 && strcmp(argv[1], "get") == 0) {
+ char *value;
+
+ value = sticker_song_get_value(song, argv[4]);
+ if (value == NULL) {
+ command_error(client, ACK_ERROR_NO_EXIST,
+ "no such sticker");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ client_printf(client, "sticker:%s=%s\n", argv[4], value);
+ g_free(value);
+
+ return COMMAND_RETURN_OK;
+ } else if (argc == 6 && strcmp(argv[1], "set") == 0) {
+ bool ret;
+
+ ret = sticker_song_set_value(song, argv[4], argv[5]);
+ if (!ret) {
+ command_error(client, ACK_ERROR_SYSTEM,
+ "failed to set sticker vqalue");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ return COMMAND_RETURN_OK;
+ } else {
+ command_error(client, ACK_ERROR_ARG, "bad request");
+ return COMMAND_RETURN_ERROR;
+ }
+}
+
+static enum command_return
+handle_sticker(struct client *client, int argc, char *argv[])
+{
+ assert(argc >= 4);
+
+ if (!sticker_enabled()) {
+ command_error(client, ACK_ERROR_UNKNOWN,
+ "sticker database is disabled");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ if (strcmp(argv[2], "song") == 0)
+ return handle_sticker_song(client, argc, argv);
+ else {
+ command_error(client, ACK_ERROR_ARG,
+ "unknown sticker domain");
+ return COMMAND_RETURN_ERROR;
+ }
+}
+#endif
+
/**
* The command registry.
*
@@ -1467,6 +1536,9 @@ static const struct command commands[] = {
{ "shuffle", PERMISSION_CONTROL, 0, 0, handle_shuffle },
{ "stats", PERMISSION_READ, 0, 0, handle_stats },
{ "status", PERMISSION_READ, 0, 0, handle_status },
+#ifdef ENABLE_SQLITE
+ { "sticker", PERMISSION_ADMIN, 3, -1, handle_sticker },
+#endif
{ "stop", PERMISSION_CONTROL, 0, 0, handle_stop },
{ "swap", PERMISSION_CONTROL, 2, 2, handle_swap },
{ "swapid", PERMISSION_CONTROL, 2, 2, handle_swapid },