mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-19 02:15:18 -04:00
[mpd] Refactor sticker commands
This commit is contained in:
parent
ef52f4ddc0
commit
7a916c84a2
235
src/mpd.c
235
src/mpd.c
@ -59,6 +59,9 @@
|
|||||||
#include "remote_pairing.h"
|
#include "remote_pairing.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MPD_ALL_IDLE_LISTENER_EVENTS (LISTENER_PLAYER | LISTENER_QUEUE | LISTENER_VOLUME | LISTENER_SPEAKER | LISTENER_OPTIONS | LISTENER_DATABASE | LISTENER_UPDATE | LISTENER_STORED_PLAYLIST | LISTENER_STICKER)
|
||||||
|
#define MPD_RATING_FACTOR 10.0
|
||||||
|
|
||||||
static pthread_t tid_mpd;
|
static pthread_t tid_mpd;
|
||||||
|
|
||||||
static struct event_base *evbase_mpd;
|
static struct event_base *evbase_mpd;
|
||||||
@ -67,8 +70,6 @@ static struct commands_base *cmdbase;
|
|||||||
|
|
||||||
static struct evhttp *evhttpd;
|
static struct evhttp *evhttpd;
|
||||||
|
|
||||||
#define ALL_IDLE_LISTENER_EVENTS (LISTENER_PLAYER | LISTENER_QUEUE | LISTENER_VOLUME | LISTENER_SPEAKER | LISTENER_OPTIONS | LISTENER_DATABASE | LISTENER_UPDATE | LISTENER_STORED_PLAYLIST | LISTENER_STICKER)
|
|
||||||
|
|
||||||
struct evconnlistener *mpd_listener6;
|
struct evconnlistener *mpd_listener6;
|
||||||
struct evconnlistener *mpd_listener;
|
struct evconnlistener *mpd_listener;
|
||||||
|
|
||||||
@ -674,7 +675,7 @@ mpd_command_idle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ctx->idle_events = ALL_IDLE_LISTENER_EVENTS;
|
ctx->idle_events = MPD_ALL_IDLE_LISTENER_EVENTS;
|
||||||
|
|
||||||
// If events the client listens to occurred since the last idle call (or since the client connected,
|
// If events the client listens to occurred since the last idle call (or since the client connected,
|
||||||
// if it is the first idle call), notify immediately.
|
// if it is the first idle call), notify immediately.
|
||||||
@ -3248,108 +3249,128 @@ mpd_command_update(struct evbuffer *evbuf, int argc, char **argv, char **errmsg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mpd_sticker_command {
|
|
||||||
const char *cmd;
|
|
||||||
int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating);
|
|
||||||
int need_args;
|
|
||||||
int want_dir;
|
|
||||||
int get_mfi;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MPD_RATING_FACTOR 10.0
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_sticker_get(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating)
|
mpd_sticker_get(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path)
|
||||||
{
|
{
|
||||||
|
struct media_file_info *mfi = NULL;
|
||||||
|
uint32_t rating;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (name_is_rating)
|
if (strcmp(argv[4], "rating") != 0)
|
||||||
{
|
|
||||||
if (!mfi || !mfi->rating)
|
|
||||||
{
|
{
|
||||||
*errmsg = safe_asprintf("no such sticker");
|
*errmsg = safe_asprintf("no such sticker");
|
||||||
ret = ACK_ERROR_NO_EXIST;
|
return ACK_ERROR_NO_EXIST;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
*rating = mfi->rating / MPD_RATING_FACTOR;
|
|
||||||
evbuffer_add_printf(evbuf, "sticker: rating=%d\n", *rating);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* |:todo:| real sticker implementation */
|
mfi = db_file_fetch_byvirtualpath(virtual_path);
|
||||||
*errmsg = safe_asprintf("no such sticker");
|
if (!mfi)
|
||||||
ret = ACK_ERROR_NO_EXIST;
|
{
|
||||||
return ret;
|
DPRINTF(E_LOG, L_MPD, "Virtual path not found: %s\n", virtual_path);
|
||||||
|
*errmsg = safe_asprintf("unknown sticker domain");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mfi && mfi->rating > 0)
|
||||||
|
{
|
||||||
|
rating = mfi->rating / MPD_RATING_FACTOR;
|
||||||
|
evbuffer_add_printf(evbuf, "sticker: rating=%d\n", rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_mfi(mfi, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_sticker_set(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating)
|
mpd_sticker_set(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path)
|
||||||
{
|
{
|
||||||
|
uint32_t rating;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (name_is_rating)
|
if (strcmp(argv[4], "rating") != 0)
|
||||||
{
|
{
|
||||||
ret = safe_atou32(argv[5], (unsigned int *) rating);
|
*errmsg = safe_asprintf("no such sticker");
|
||||||
|
return ACK_ERROR_NO_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safe_atou32(argv[5], &rating);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
*errmsg = safe_asprintf("rating '%s' doesn't convert to integer", argv[5]);
|
*errmsg = safe_asprintf("rating '%s' doesn't convert to integer", argv[5]);
|
||||||
ret = ACK_ERROR_ARG;
|
return ACK_ERROR_ARG;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
*rating *= MPD_RATING_FACTOR;
|
|
||||||
*set_rating = 1;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* |:todo:| real sticker implementation */
|
rating *= MPD_RATING_FACTOR;
|
||||||
|
ret = db_file_rating_update_byvirtualpath(virtual_path, rating);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
*errmsg = safe_asprintf("Invalid path '%s'", virtual_path);
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mpd_sticker_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (strcmp(argv[4], "rating") != 0)
|
||||||
|
{
|
||||||
*errmsg = safe_asprintf("no such sticker");
|
*errmsg = safe_asprintf("no such sticker");
|
||||||
ret = ACK_ERROR_NO_EXIST;
|
return ACK_ERROR_NO_EXIST;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
mpd_sticker_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (name_is_rating)
|
|
||||||
{
|
|
||||||
*rating = 0;
|
|
||||||
*set_rating = 1;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* |:todo:| real sticker implementation */
|
ret = db_file_rating_update_byvirtualpath(virtual_path, 0);
|
||||||
*errmsg = safe_asprintf("no such sticker");
|
if (ret <= 0)
|
||||||
ret = ACK_ERROR_NO_EXIST;
|
{
|
||||||
return ret;
|
*errmsg = safe_asprintf("Invalid path '%s'", virtual_path);
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_sticker_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating)
|
mpd_sticker_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path)
|
||||||
{
|
{
|
||||||
|
struct media_file_info *mfi = NULL;
|
||||||
|
uint32_t rating;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (mfi && mfi->rating)
|
mfi = db_file_fetch_byvirtualpath(virtual_path);
|
||||||
|
if (!mfi)
|
||||||
{
|
{
|
||||||
*rating = mfi->rating / MPD_RATING_FACTOR;
|
DPRINTF(E_LOG, L_MPD, "Virtual path not found: %s\n", virtual_path);
|
||||||
evbuffer_add_printf(evbuf, "sticker: rating=%d\n", *rating);
|
*errmsg = safe_asprintf("unknown sticker domain");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mfi && mfi->rating > 0)
|
||||||
|
{
|
||||||
|
rating = mfi->rating / MPD_RATING_FACTOR;
|
||||||
|
evbuffer_add_printf(evbuf, "sticker: rating=%d\n", rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_mfi(mfi, 0);
|
||||||
|
|
||||||
/* |:todo:| real sticker implementation */
|
/* |:todo:| real sticker implementation */
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_sticker_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *name, const char *virtual_path, bool name_is_rating, struct media_file_info *mfi, int *rating, bool *set_rating)
|
mpd_sticker_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (name_is_rating && argc == 5)
|
|
||||||
{
|
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct db_media_file_info dbmfi;
|
struct db_media_file_info dbmfi;
|
||||||
char *c1;
|
uint32_t rating;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (strcmp(argv[4], "rating") != 0)
|
||||||
|
{
|
||||||
|
*errmsg = safe_asprintf("no such sticker");
|
||||||
|
return ACK_ERROR_NO_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&qp, 0, sizeof(struct query_params));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
@ -3357,14 +3378,13 @@ mpd_sticker_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, c
|
|||||||
qp.sort = S_VPATH;
|
qp.sort = S_VPATH;
|
||||||
qp.idx_type = I_NONE;
|
qp.idx_type = I_NONE;
|
||||||
|
|
||||||
c1 = db_mprintf("(f.virtual_path LIKE '%s%%' AND f.rating != 0)", virtual_path);
|
qp.filter = db_mprintf("(f.virtual_path LIKE '%s%%' AND f.rating > 0)", virtual_path);
|
||||||
if (!c1)
|
if (!qp.filter)
|
||||||
{
|
{
|
||||||
*errmsg = safe_asprintf("Out of memory");
|
*errmsg = safe_asprintf("Out of memory");
|
||||||
ret = ACK_ERROR_UNKNOWN;
|
ret = ACK_ERROR_UNKNOWN;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
qp.filter = c1;
|
|
||||||
|
|
||||||
ret = db_query_start(&qp);
|
ret = db_query_start(&qp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -3379,48 +3399,42 @@ mpd_sticker_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, c
|
|||||||
|
|
||||||
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
|
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
|
||||||
{
|
{
|
||||||
ret = safe_atou32(dbmfi.rating, (unsigned int *) rating);
|
ret = safe_atou32(dbmfi.rating, &rating);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Error rating=%s doesn't convert to integer, song id: %s\n",
|
DPRINTF(E_LOG, L_MPD, "Error rating=%s doesn't convert to integer, song id: %s\n",
|
||||||
dbmfi.rating, dbmfi.id);
|
dbmfi.rating, dbmfi.id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*rating /= MPD_RATING_FACTOR;
|
|
||||||
if (!*rating)
|
|
||||||
/* inconsistent database */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
rating /= MPD_RATING_FACTOR;
|
||||||
ret = evbuffer_add_printf(evbuf,
|
ret = evbuffer_add_printf(evbuf,
|
||||||
"file: file:%s\n"
|
"file: file:%s\n"
|
||||||
"sticker: rating=%d\n",
|
"sticker: rating=%d\n",
|
||||||
dbmfi.path,
|
dbmfi.path,
|
||||||
*rating);
|
rating);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_MPD, "Error adding song to the evbuffer, song id: %s\n", dbmfi.id);
|
DPRINTF(E_LOG, L_MPD, "Error adding song to the evbuffer, song id: %s\n", dbmfi.id);
|
||||||
}
|
}
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
free(qp.filter);
|
free(qp.filter);
|
||||||
return ret;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* |:todo:| MPD_STICKER_FIND with expressions */
|
|
||||||
|
|
||||||
/* |:todo:| real sticker implementation */
|
|
||||||
*errmsg = safe_asprintf("bad request");
|
|
||||||
ret = ACK_ERROR_ARG;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mpd_sticker_command {
|
||||||
|
const char *cmd;
|
||||||
|
int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, const char *virtual_path);
|
||||||
|
int need_args;
|
||||||
|
};
|
||||||
|
|
||||||
static struct mpd_sticker_command mpd_sticker_handlers[] = {
|
static struct mpd_sticker_command mpd_sticker_handlers[] = {
|
||||||
{ "get", mpd_sticker_get, 5, 0, 0 },
|
{ "get", mpd_sticker_get, 5 },
|
||||||
{ "set", mpd_sticker_set, 6, 0, 0 },
|
{ "set", mpd_sticker_set, 6 },
|
||||||
{ "delete", mpd_sticker_delete, 5, 0, 0 },
|
{ "delete", mpd_sticker_delete, 5 },
|
||||||
{ "list", mpd_sticker_list, 4, 0, 1 },
|
{ "list", mpd_sticker_list, 4 },
|
||||||
{ "find", mpd_sticker_find, 5, 1, 0 },
|
{ "find", mpd_sticker_find, 5 },
|
||||||
{ NULL, NULL, 0, 0, 0 },
|
{ NULL, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3444,13 +3458,7 @@ static int
|
|||||||
mpd_command_sticker(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
mpd_command_sticker(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct mpd_sticker_command *cmd_param;
|
struct mpd_sticker_command *cmd_param;
|
||||||
const char *cmd;
|
|
||||||
char *virtual_path = NULL;
|
char *virtual_path = NULL;
|
||||||
const char *name = NULL;
|
|
||||||
bool name_is_rating = false;
|
|
||||||
struct media_file_info *mfi = NULL;
|
|
||||||
int rating = -1;
|
|
||||||
bool set_rating = false;
|
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -3466,11 +3474,10 @@ mpd_command_sticker(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||||||
return ACK_ERROR_ARG;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = argv[1];
|
|
||||||
for (i=0; i<(sizeof(mpd_sticker_handlers) / sizeof(struct mpd_sticker_command)); ++i)
|
for (i=0; i<(sizeof(mpd_sticker_handlers) / sizeof(struct mpd_sticker_command)); ++i)
|
||||||
{
|
{
|
||||||
cmd_param = &mpd_sticker_handlers[i];
|
cmd_param = &mpd_sticker_handlers[i];
|
||||||
if (cmd_param->cmd && strcmp(cmd, cmd_param->cmd) == 0)
|
if (cmd_param->cmd && strcmp(argv[1], cmd_param->cmd) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!cmd_param->cmd)
|
if (!cmd_param->cmd)
|
||||||
@ -3484,38 +3491,12 @@ mpd_command_sticker(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||||||
return ACK_ERROR_ARG;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 4)
|
|
||||||
{
|
|
||||||
name = argv[4];
|
|
||||||
name_is_rating = strcmp(name, "rating") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual_path = prepend_slash(argv[3]);
|
virtual_path = prepend_slash(argv[3]);
|
||||||
|
|
||||||
if (cmd_param->get_mfi || (!cmd_param->want_dir && name_is_rating))
|
ret = cmd_param->handler(evbuf, argc, argv, errmsg, virtual_path);
|
||||||
{
|
|
||||||
mfi = db_file_fetch_byvirtualpath(virtual_path);
|
|
||||||
if (!mfi)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Virtual path not found: %s\n", virtual_path);
|
|
||||||
*errmsg = safe_asprintf("unknown sticker domain");
|
|
||||||
free(virtual_path);
|
|
||||||
return ACK_ERROR_ARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = cmd_param->handler(evbuf, argc, argv, errmsg, name, virtual_path, name_is_rating, mfi, &rating, &set_rating);
|
|
||||||
|
|
||||||
if (ret == 0 && mfi && set_rating && mfi->rating != rating)
|
|
||||||
{
|
|
||||||
db_file_rating_update_byvirtualpath(virtual_path, rating);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(virtual_path);
|
free(virtual_path);
|
||||||
|
|
||||||
if (mfi)
|
|
||||||
free_mfi(mfi, 0);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5396,7 +5377,7 @@ int mpd_init(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
mpd_clients = NULL;
|
mpd_clients = NULL;
|
||||||
listener_add(mpd_listener_cb, ALL_IDLE_LISTENER_EVENTS);
|
listener_add(mpd_listener_cb, MPD_ALL_IDLE_LISTENER_EVENTS);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user