Add sticker list command.

[mk: merged memory leak patch; fixed indentation (tabs); fixed
documentation typo]
This commit is contained in:
Eric Wollesen 2009-03-03 07:49:23 +01:00 committed by Max Kellermann
parent 95b53281a4
commit b8ebb748c9
6 changed files with 153 additions and 4 deletions

View File

@ -1222,6 +1222,21 @@ OK
</para> </para>
</listitem> </listitem>
</varlistentry> </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> </variablelist>
</section> </section>

View File

@ -1472,6 +1472,34 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
client_printf(client, "sticker: %s=%s\n", argv[4], value); client_printf(client, "sticker: %s=%s\n", argv[4], value);
g_free(value); 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; return COMMAND_RETURN_OK;
} else if (argc == 6 && strcmp(argv[1], "set") == 0) { } else if (argc == 6 && strcmp(argv[1], "set") == 0) {
bool ret; bool ret;
@ -1479,7 +1507,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
ret = sticker_song_set_value(song, argv[4], argv[5]); ret = sticker_song_set_value(song, argv[4], argv[5]);
if (!ret) { if (!ret) {
command_error(client, ACK_ERROR_SYSTEM, command_error(client, ACK_ERROR_SYSTEM,
"failed to set sticker vqalue"); "failed to set sticker value");
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }

View File

@ -39,6 +39,22 @@ sticker_song_get_value(const struct song *song, const char *name)
return value; 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 bool
sticker_song_set_value(const struct song *song, sticker_song_set_value(const struct song *song,
const char *name, const char *value) const char *name, const char *value)

View File

@ -20,6 +20,7 @@
#define SONG_STICKER_H #define SONG_STICKER_H
#include <stdbool.h> #include <stdbool.h>
#include <glib.h>
struct song; struct song;
@ -38,6 +39,15 @@ bool
sticker_song_set_value(const struct song *song, sticker_song_set_value(const struct song *song,
const char *name, const char *value); 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. * Deletes a sticker from the database. All values are deleted.
*/ */

View File

@ -40,6 +40,9 @@ static const char sticker_sql_create[] =
static const char sticker_sql_get[] = static const char sticker_sql_get[] =
"SELECT value FROM sticker WHERE type=? AND uri=? AND name=?"; "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[] = static const char sticker_sql_update[] =
"UPDATE sticker SET value=? WHERE type=? AND uri=? AND name=?"; "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=?"; "DELETE FROM sticker WHERE type=? AND uri=?";
static sqlite3 *sticker_db; static sqlite3 *sticker_db;
static sqlite3_stmt *sticker_stmt_get, *sticker_stmt_update, static sqlite3_stmt *sticker_stmt_get, *sticker_stmt_list,
*sticker_stmt_insert, *sticker_stmt_delete; *sticker_stmt_update, *sticker_stmt_insert,
*sticker_stmt_delete;
static sqlite3_stmt * static sqlite3_stmt *
sticker_prepare(const char *sql) sticker_prepare(const char *sql)
@ -93,12 +97,14 @@ sticker_global_init(const char *path)
/* prepare the statements we're going to use */ /* prepare the statements we're going to use */
sticker_stmt_get = sticker_prepare(sticker_sql_get); 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_update = sticker_prepare(sticker_sql_update);
sticker_stmt_insert = sticker_prepare(sticker_sql_insert); sticker_stmt_insert = sticker_prepare(sticker_sql_insert);
sticker_stmt_delete = sticker_prepare(sticker_sql_delete); sticker_stmt_delete = sticker_prepare(sticker_sql_delete);
if (sticker_stmt_get == NULL || sticker_stmt_update == NULL || 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"); g_error("Failed to prepare sqlite statements");
} }
@ -112,6 +118,8 @@ sticker_global_finish(void)
sqlite3_finalize(sticker_stmt_delete); sqlite3_finalize(sticker_stmt_delete);
sqlite3_finalize(sticker_stmt_update); sqlite3_finalize(sticker_stmt_update);
sqlite3_finalize(sticker_stmt_insert); sqlite3_finalize(sticker_stmt_insert);
sqlite3_finalize(sticker_stmt_list);
sqlite3_finalize(sticker_stmt_get);
sqlite3_close(sticker_db); sqlite3_close(sticker_db);
} }
@ -181,6 +189,67 @@ sticker_load_value(const char *type, const char *uri, const char *name)
return value; 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 static bool
sticker_update_value(const char *type, const char *uri, sticker_update_value(const char *type, const char *uri,
const char *name, const char *value) const char *name, const char *value)

View File

@ -41,6 +41,8 @@
#ifndef STICKER_H #ifndef STICKER_H
#define STICKER_H #define STICKER_H
#include <glib.h>
#include <stdbool.h> #include <stdbool.h>
/** /**
@ -61,6 +63,15 @@ sticker_global_finish(void);
bool bool
sticker_enabled(void); 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 * Returns one value from an object's sticker record. The caller must
* free the return value with g_free(). * free the return value with g_free().