summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wollesen <ericw@xmtp.net>2009-03-03 07:49:23 +0100
committerMax Kellermann <max@duempel.org>2009-03-03 07:49:23 +0100
commitb8ebb748c9e4da74c361c3b4e5840891eaf22864 (patch)
tree69368bd8f3e382be05644601f44b117c40ffdd45
parent95b53281a45841bc4d981f131ac452615e923575 (diff)
Add sticker list command.
[mk: merged memory leak patch; fixed indentation (tabs); fixed documentation typo]
-rw-r--r--doc/protocol.xml15
-rw-r--r--src/command.c30
-rw-r--r--src/song_sticker.c16
-rw-r--r--src/song_sticker.h10
-rw-r--r--src/sticker.c75
-rw-r--r--src/sticker.h11
6 files changed, 153 insertions, 4 deletions
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 364384e1f..14d286c63 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -1222,6 +1222,21 @@ OK
</para>
</listitem>
</varlistentry>
+ <varlistentry id="command_sticker_list">
+ <term>
+ <cmdsynopsis>
+ <command>sticker</command>
+ <arg choice="plain">list</arg>
+ <arg choice="req"><replaceable>TYPE</replaceable></arg>
+ <arg choice="req"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ </term>
+ <listitem>
+ <para>
+ Lists the stickers for the specified object.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</section>
diff --git a/src/command.c b/src/command.c
index 6f97e06ef..5342662ca 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1473,13 +1473,41 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
g_free(value);
return COMMAND_RETURN_OK;
+ } else if (argc == 4 && strcmp(argv[1], "list") == 0) {
+ GList *list;
+ GPtrArray *values;
+ unsigned int x;
+
+ list = sticker_song_list_values(song);
+ if (NULL == list) {
+ command_error(client, ACK_ERROR_NO_EXIST,
+ "no stickers found");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ for (x = 0; x < g_list_length(list); x++) {
+ values = g_list_nth_data(list, x);
+ if (NULL == values) {
+ g_warning("NULL sticker found");
+ continue;
+ }
+ client_printf(client, "sticker: %s=%s\n",
+ (char *)g_ptr_array_index(values, 0),
+ (char *)g_ptr_array_index(values, 1));
+ g_free(g_ptr_array_index(values, 0));
+ g_free(g_ptr_array_index(values, 1));
+ g_ptr_array_free(values, TRUE);
+ }
+ g_list_free(list);
+
+ 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");
+ "failed to set sticker value");
return COMMAND_RETURN_ERROR;
}
diff --git a/src/song_sticker.c b/src/song_sticker.c
index cdd3f84c3..bf400c15b 100644
--- a/src/song_sticker.c
+++ b/src/song_sticker.c
@@ -39,6 +39,22 @@ sticker_song_get_value(const struct song *song, const char *name)
return value;
}
+GList *
+sticker_song_list_values(const struct song *song)
+{
+ char *uri;
+ GList *list;
+
+ assert(song != NULL);
+ assert(song_in_database(song));
+
+ uri = song_get_uri(song);
+ list = sticker_list_values("song", uri);
+ g_free(uri);
+
+ return list;
+}
+
bool
sticker_song_set_value(const struct song *song,
const char *name, const char *value)
diff --git a/src/song_sticker.h b/src/song_sticker.h
index a09279c52..68124580f 100644
--- a/src/song_sticker.h
+++ b/src/song_sticker.h
@@ -20,6 +20,7 @@
#define SONG_STICKER_H
#include <stdbool.h>
+#include <glib.h>
struct song;
@@ -39,6 +40,15 @@ sticker_song_set_value(const struct song *song,
const char *name, const char *value);
/**
+ * Returns a list of key value pairs from a song's sticker record.
+ * The caller must free each GPtrArray element of the returned list
+ * with g_ptr_array_free(), as well as the returned GList with
+ * g_list_free().
+ */
+GList *
+sticker_song_list_values(const struct song *song);
+
+/**
* Deletes a sticker from the database. All values are deleted.
*/
bool
diff --git a/src/sticker.c b/src/sticker.c
index 1c838983b..f27df7cf7 100644
--- a/src/sticker.c
+++ b/src/sticker.c
@@ -40,6 +40,9 @@ static const char sticker_sql_create[] =
static const char sticker_sql_get[] =
"SELECT value FROM sticker WHERE type=? AND uri=? AND name=?";
+static const char sticker_sql_list[] =
+ "SELECT name,value FROM sticker WHERE type=? AND uri=?";
+
static const char sticker_sql_update[] =
"UPDATE sticker SET value=? WHERE type=? AND uri=? AND name=?";
@@ -50,8 +53,9 @@ static const char sticker_sql_delete[] =
"DELETE FROM sticker WHERE type=? AND uri=?";
static sqlite3 *sticker_db;
-static sqlite3_stmt *sticker_stmt_get, *sticker_stmt_update,
- *sticker_stmt_insert, *sticker_stmt_delete;
+static sqlite3_stmt *sticker_stmt_get, *sticker_stmt_list,
+ *sticker_stmt_update, *sticker_stmt_insert,
+ *sticker_stmt_delete;
static sqlite3_stmt *
sticker_prepare(const char *sql)
@@ -93,12 +97,14 @@ sticker_global_init(const char *path)
/* prepare the statements we're going to use */
sticker_stmt_get = sticker_prepare(sticker_sql_get);
+ sticker_stmt_list = sticker_prepare(sticker_sql_list);
sticker_stmt_update = sticker_prepare(sticker_sql_update);
sticker_stmt_insert = sticker_prepare(sticker_sql_insert);
sticker_stmt_delete = sticker_prepare(sticker_sql_delete);
if (sticker_stmt_get == NULL || sticker_stmt_update == NULL ||
- sticker_stmt_insert == NULL || sticker_stmt_delete == NULL)
+ sticker_stmt_insert == NULL || sticker_stmt_delete == NULL ||
+ sticker_stmt_list == NULL)
g_error("Failed to prepare sqlite statements");
}
@@ -112,6 +118,8 @@ sticker_global_finish(void)
sqlite3_finalize(sticker_stmt_delete);
sqlite3_finalize(sticker_stmt_update);
sqlite3_finalize(sticker_stmt_insert);
+ sqlite3_finalize(sticker_stmt_list);
+ sqlite3_finalize(sticker_stmt_get);
sqlite3_close(sticker_db);
}
@@ -181,6 +189,67 @@ sticker_load_value(const char *type, const char *uri, const char *name)
return value;
}
+GList *
+sticker_list_values(const char *type, const char *uri)
+{
+ int ret;
+ char *name, *value;
+ GPtrArray *arr;
+ GList *list;
+
+ list = NULL;
+ assert(type != NULL);
+ assert(uri != NULL);
+
+ assert(sticker_enabled());
+
+ sqlite3_reset(sticker_stmt_list);
+
+ ret = sqlite3_bind_text(sticker_stmt_list, 1, type, -1, NULL);
+ if (ret != SQLITE_OK) {
+ g_warning("sqlite3_bind_text() failed: %s",
+ sqlite3_errmsg(sticker_db));
+ return NULL;
+ }
+
+ ret = sqlite3_bind_text(sticker_stmt_list, 2, uri, -1, NULL);
+ if (ret != SQLITE_OK) {
+ g_warning("sqlite3_bind_text() failed: %s",
+ sqlite3_errmsg(sticker_db));
+ return NULL;
+ }
+
+ do {
+ ret = sqlite3_step(sticker_stmt_list);
+ switch (ret) {
+ case SQLITE_ROW:
+ name = g_strdup((const char*)sqlite3_column_text(sticker_stmt_list, 0));
+ value = g_strdup((const char*)sqlite3_column_text(sticker_stmt_list, 1));
+ arr = g_ptr_array_new();
+ g_ptr_array_add(arr, name);
+ g_ptr_array_add(arr, value);
+ list = g_list_prepend(list, arr);
+ break;
+ case SQLITE_DONE:
+ break;
+ case SQLITE_BUSY:
+ /* no op */
+ break;
+ default:
+ g_warning("sqlite3_step() failed: %s",
+ sqlite3_errmsg(sticker_db));
+ return NULL;
+ }
+ } while (ret != SQLITE_DONE);
+
+ list = g_list_reverse(list);
+
+ sqlite3_reset(sticker_stmt_list);
+ sqlite3_clear_bindings(sticker_stmt_list);
+
+ return list;
+}
+
static bool
sticker_update_value(const char *type, const char *uri,
const char *name, const char *value)
diff --git a/src/sticker.h b/src/sticker.h
index ab3a35572..689555fb0 100644
--- a/src/sticker.h
+++ b/src/sticker.h
@@ -41,6 +41,8 @@
#ifndef STICKER_H
#define STICKER_H
+#include <glib.h>
+
#include <stdbool.h>
/**
@@ -62,6 +64,15 @@ bool
sticker_enabled(void);
/**
+ * Populates a GList with GPtrArrays of sticker names and values from
+ * an object's sticker record. The caller must free each GPtrArray
+ * element of the returned list with g_ptr_array_free(), as well as
+ * the returned GList with g_list_free().
+ */
+GList *
+sticker_list_values(const char *type, const char *uri);
+
+/**
* Returns one value from an object's sticker record. The caller must
* free the return value with g_free().
*/