Add sticker list command.
[mk: merged memory leak patch; fixed indentation (tabs); fixed documentation typo]
This commit is contained in:
parent
95b53281a4
commit
b8ebb748c9
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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)
|
||||||
|
@ -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().
|
||||||
|
Loading…
Reference in New Issue
Block a user