sticker: new library for storing dynamic information about songs
"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.
This commit is contained in:
parent
fbed96dcea
commit
145ab84d51
@ -43,6 +43,10 @@ The default is "yes".
|
|||||||
.B db_file <file>
|
.B db_file <file>
|
||||||
This specifies where the db file will be stored.
|
This specifies where the db file will be stored.
|
||||||
.TP
|
.TP
|
||||||
|
.B sticker_file <file>
|
||||||
|
The location of the sticker database. This is a database which
|
||||||
|
manages dynamic information attached to songs.
|
||||||
|
.TP
|
||||||
.B log_file <file>
|
.B log_file <file>
|
||||||
This specifies where the log file should be located.
|
This specifies where the log file should be located.
|
||||||
The special value "syslog" makes MPD use the local syslog daemon.
|
The special value "syslog" makes MPD use the local syslog daemon.
|
||||||
|
@ -100,6 +100,7 @@ mpd_headers = \
|
|||||||
songvec.h \
|
songvec.h \
|
||||||
state_file.h \
|
state_file.h \
|
||||||
stats.h \
|
stats.h \
|
||||||
|
sticker.h \
|
||||||
tag.h \
|
tag.h \
|
||||||
tag_internal.h \
|
tag_internal.h \
|
||||||
tag_pool.h \
|
tag_pool.h \
|
||||||
@ -192,6 +193,10 @@ mpd_SOURCES = \
|
|||||||
stored_playlist.c \
|
stored_playlist.c \
|
||||||
timer.c
|
timer.c
|
||||||
|
|
||||||
|
if ENABLE_SQLITE
|
||||||
|
mpd_SOURCES += sticker.c
|
||||||
|
endif
|
||||||
|
|
||||||
if HAVE_LIBSAMPLERATE
|
if HAVE_LIBSAMPLERATE
|
||||||
mpd_SOURCES += pcm_resample_libsamplerate.c
|
mpd_SOURCES += pcm_resample_libsamplerate.c
|
||||||
else
|
else
|
||||||
|
@ -172,6 +172,7 @@ void config_global_init(void)
|
|||||||
registerConfigParam(CONF_FOLLOW_INSIDE_SYMLINKS, 0, 0);
|
registerConfigParam(CONF_FOLLOW_INSIDE_SYMLINKS, 0, 0);
|
||||||
registerConfigParam(CONF_FOLLOW_OUTSIDE_SYMLINKS, 0, 0);
|
registerConfigParam(CONF_FOLLOW_OUTSIDE_SYMLINKS, 0, 0);
|
||||||
registerConfigParam(CONF_DB_FILE, 0, 0);
|
registerConfigParam(CONF_DB_FILE, 0, 0);
|
||||||
|
registerConfigParam(CONF_STICKER_FILE, false, false);
|
||||||
registerConfigParam(CONF_LOG_FILE, 0, 0);
|
registerConfigParam(CONF_LOG_FILE, 0, 0);
|
||||||
registerConfigParam(CONF_ERROR_FILE, 0, 0);
|
registerConfigParam(CONF_ERROR_FILE, 0, 0);
|
||||||
registerConfigParam(CONF_PID_FILE, 0, 0);
|
registerConfigParam(CONF_PID_FILE, 0, 0);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#define CONF_FOLLOW_INSIDE_SYMLINKS "follow_inside_symlinks"
|
#define CONF_FOLLOW_INSIDE_SYMLINKS "follow_inside_symlinks"
|
||||||
#define CONF_FOLLOW_OUTSIDE_SYMLINKS "follow_outside_symlinks"
|
#define CONF_FOLLOW_OUTSIDE_SYMLINKS "follow_outside_symlinks"
|
||||||
#define CONF_DB_FILE "db_file"
|
#define CONF_DB_FILE "db_file"
|
||||||
|
#define CONF_STICKER_FILE "sticker_file"
|
||||||
#define CONF_LOG_FILE "log_file"
|
#define CONF_LOG_FILE "log_file"
|
||||||
#define CONF_ERROR_FILE "error_file"
|
#define CONF_ERROR_FILE "error_file"
|
||||||
#define CONF_PID_FILE "pid_file"
|
#define CONF_PID_FILE "pid_file"
|
||||||
|
12
src/main.c
12
src/main.c
@ -54,6 +54,10 @@
|
|||||||
#include "songvec.h"
|
#include "songvec.h"
|
||||||
#include "tag_pool.h"
|
#include "tag_pool.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SQLITE
|
||||||
|
#include "sticker.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_ARCHIVE
|
#ifdef ENABLE_ARCHIVE
|
||||||
#include "archive_list.h"
|
#include "archive_list.h"
|
||||||
#endif
|
#endif
|
||||||
@ -235,6 +239,10 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
openDB(&options, argv[0]);
|
openDB(&options, argv[0]);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SQLITE
|
||||||
|
sticker_global_init(config_get_path(CONF_STICKER_FILE));
|
||||||
|
#endif
|
||||||
|
|
||||||
command_init();
|
command_init();
|
||||||
initialize_decoder_and_player();
|
initialize_decoder_and_player();
|
||||||
initAudioConfig();
|
initAudioConfig();
|
||||||
@ -278,6 +286,10 @@ int main(int argc, char *argv[])
|
|||||||
g_debug("db_finish took %f seconds",
|
g_debug("db_finish took %f seconds",
|
||||||
((float)(clock()-start))/CLOCKS_PER_SEC);
|
((float)(clock()-start))/CLOCKS_PER_SEC);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SQLITE
|
||||||
|
sticker_global_finish();
|
||||||
|
#endif
|
||||||
|
|
||||||
notify_deinit(&main_notify);
|
notify_deinit(&main_notify);
|
||||||
event_pipe_deinit();
|
event_pipe_deinit();
|
||||||
|
|
||||||
|
361
src/sticker.c
Normal file
361
src/sticker.c
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2009 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sticker.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#undef G_LOG_DOMAIN
|
||||||
|
#define G_LOG_DOMAIN "sticker"
|
||||||
|
|
||||||
|
static const char sticker_sql_create[] =
|
||||||
|
"CREATE TABLE IF NOT EXISTS sticker("
|
||||||
|
" type VARCHAR NOT NULL, "
|
||||||
|
" uri VARCHAR NOT NULL, "
|
||||||
|
" name VARCHAR NOT NULL, "
|
||||||
|
" value VARCHAR NOT NULL"
|
||||||
|
");"
|
||||||
|
"CREATE UNIQUE INDEX IF NOT EXISTS"
|
||||||
|
" sticker_value ON sticker(type, uri, name);"
|
||||||
|
"";
|
||||||
|
|
||||||
|
static const char sticker_sql_get[] =
|
||||||
|
"SELECT value FROM sticker WHERE type=? AND uri=? AND name=?";
|
||||||
|
|
||||||
|
static const char sticker_sql_update[] =
|
||||||
|
"UPDATE sticker SET value=? WHERE type=? AND uri=? AND name=?";
|
||||||
|
|
||||||
|
static const char sticker_sql_insert[] =
|
||||||
|
"INSERT INTO sticker(type,uri,name,value) VALUES(?, ?, ?, ?)";
|
||||||
|
|
||||||
|
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_prepare(const char *sql)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
sqlite3_stmt *stmt;
|
||||||
|
|
||||||
|
ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, NULL);
|
||||||
|
if (ret != SQLITE_OK)
|
||||||
|
g_error("sqlite3_prepare_v2() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sticker_global_init(const char *path)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (path == NULL)
|
||||||
|
/* not configured */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* open/create the sqlite database */
|
||||||
|
|
||||||
|
ret = sqlite3_open(path, &sticker_db);
|
||||||
|
if (ret != SQLITE_OK)
|
||||||
|
g_error("Failed to open sqlite database '%s': %s",
|
||||||
|
path, sqlite3_errmsg(sticker_db));
|
||||||
|
|
||||||
|
/* create the table and index */
|
||||||
|
|
||||||
|
ret = sqlite3_exec(sticker_db, sticker_sql_create, NULL, NULL, NULL);
|
||||||
|
if (ret != SQLITE_OK)
|
||||||
|
g_error("Failed to create sticker table: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
|
||||||
|
/* prepare the statements we're going to use */
|
||||||
|
|
||||||
|
sticker_stmt_get = sticker_prepare(sticker_sql_get);
|
||||||
|
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)
|
||||||
|
g_error("Failed to prepare sqlite statements");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sticker_global_finish(void)
|
||||||
|
{
|
||||||
|
if (sticker_db == NULL)
|
||||||
|
/* not configured */
|
||||||
|
return;
|
||||||
|
|
||||||
|
sqlite3_finalize(sticker_stmt_delete);
|
||||||
|
sqlite3_finalize(sticker_stmt_update);
|
||||||
|
sqlite3_finalize(sticker_stmt_insert);
|
||||||
|
sqlite3_close(sticker_db);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sticker_enabled(void)
|
||||||
|
{
|
||||||
|
return sticker_db != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
sticker_load_value(const char *type, const char *uri, const char *name)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
assert(sticker_enabled());
|
||||||
|
assert(type != NULL);
|
||||||
|
assert(uri != NULL);
|
||||||
|
assert(name != NULL);
|
||||||
|
|
||||||
|
if (*name == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_get);
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_get, 1, type, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_get, 2, uri, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_get, 3, name, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sqlite3_step(sticker_stmt_get);
|
||||||
|
} while (ret == SQLITE_BUSY);
|
||||||
|
|
||||||
|
if (ret == SQLITE_ROW) {
|
||||||
|
/* record found */
|
||||||
|
value = g_strdup((const char*)sqlite3_column_text(sticker_stmt_get, 0));
|
||||||
|
} else if (ret == SQLITE_DONE) {
|
||||||
|
/* no record found */
|
||||||
|
value = NULL;
|
||||||
|
} else {
|
||||||
|
/* error */
|
||||||
|
g_warning("sqlite3_step() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_get);
|
||||||
|
sqlite3_clear_bindings(sticker_stmt_get);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sticker_update_value(const char *type, const char *uri,
|
||||||
|
const char *name, const char *value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(type != NULL);
|
||||||
|
assert(uri != NULL);
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(*name != 0);
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
assert(sticker_enabled());
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_update);
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_update, 1, value, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_update, 2, type, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_update, 3, uri, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_update, 4, name, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sqlite3_step(sticker_stmt_update);
|
||||||
|
} while (ret == SQLITE_BUSY);
|
||||||
|
|
||||||
|
if (ret != SQLITE_DONE) {
|
||||||
|
g_warning("sqlite3_step() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_changes(sticker_db);
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_update);
|
||||||
|
sqlite3_clear_bindings(sticker_stmt_update);
|
||||||
|
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sticker_insert_value(const char *type, const char *uri,
|
||||||
|
const char *name, const char *value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(type != NULL);
|
||||||
|
assert(uri != NULL);
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(*name != 0);
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
assert(sticker_enabled());
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_insert);
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_insert, 1, type, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_insert, 2, uri, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_insert, 3, name, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_insert, 4, value, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sqlite3_step(sticker_stmt_insert);
|
||||||
|
} while (ret == SQLITE_BUSY);
|
||||||
|
|
||||||
|
if (ret != SQLITE_DONE) {
|
||||||
|
g_warning("sqlite3_step() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_insert);
|
||||||
|
sqlite3_clear_bindings(sticker_stmt_insert);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sticker_store_value(const char *type, const char *uri,
|
||||||
|
const char *name, const char *value)
|
||||||
|
{
|
||||||
|
assert(sticker_enabled());
|
||||||
|
assert(type != NULL);
|
||||||
|
assert(uri != NULL);
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
if (*name == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sticker_update_value(type, uri, name, value) ||
|
||||||
|
sticker_insert_value(type, uri, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sticker_delete(const char *type, const char *uri)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(sticker_enabled());
|
||||||
|
assert(type != NULL);
|
||||||
|
assert(uri != NULL);
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_delete);
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_delete, 1, type, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_bind_text(sticker_stmt_delete, 2, uri, -1, NULL);
|
||||||
|
if (ret != SQLITE_OK) {
|
||||||
|
g_warning("sqlite3_bind_text() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sqlite3_step(sticker_stmt_delete);
|
||||||
|
} while (ret == SQLITE_BUSY);
|
||||||
|
|
||||||
|
if (ret != SQLITE_DONE) {
|
||||||
|
g_warning("sqlite3_step() failed: %s",
|
||||||
|
sqlite3_errmsg(sticker_db));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(sticker_stmt_delete);
|
||||||
|
sqlite3_clear_bindings(sticker_stmt_delete);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
86
src/sticker.h
Normal file
86
src/sticker.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2009 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the sticker database library. It is the backend of all the
|
||||||
|
* sticker code in MPD.
|
||||||
|
*
|
||||||
|
* "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.
|
||||||
|
*
|
||||||
|
* 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).
|
||||||
|
*
|
||||||
|
* Client developers should create a standard for common sticker
|
||||||
|
* names, to ensure interoperability.
|
||||||
|
*
|
||||||
|
* Examples: song ratings; statistics; deferred tag writes; lyrics;
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STICKER_H
|
||||||
|
#define STICKER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the sticker database (if path is not NULL).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sticker_global_init(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the sticker database.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sticker_global_finish(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the sticker database is configured and available.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
sticker_enabled(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns one value from an object's sticker record. The caller must
|
||||||
|
* free the return value with g_free().
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
sticker_load_value(const char *type, const char *uri, const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a sticker value in the specified object. Overwrites existing
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
sticker_store_value(const char *type, const char *uri,
|
||||||
|
const char *name, const char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a sticker from the database. All sticker values of the
|
||||||
|
* specified object are deleted.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
sticker_delete(const char *type, const char *uri);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user