diff options
-rw-r--r-- | doc/protocol.xml | 15 | ||||
-rw-r--r-- | src/command.c | 30 | ||||
-rw-r--r-- | src/song_sticker.c | 16 | ||||
-rw-r--r-- | src/song_sticker.h | 10 | ||||
-rw-r--r-- | src/sticker.c | 75 | ||||
-rw-r--r-- | src/sticker.h | 11 |
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(). */ |