mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-09 12:48:09 -05:00
Better support for playqueue-edit (command add, mode 1)
- reply message not fixed
This commit is contained in:
parent
ecd8b5d940
commit
a4c16741d9
@ -12,6 +12,7 @@ struct dmap_query_field_map;
|
|||||||
%%
|
%%
|
||||||
"dmap.itemname", "f.title", 0
|
"dmap.itemname", "f.title", 0
|
||||||
"dmap.itemid", "f.id", 1
|
"dmap.itemid", "f.id", 1
|
||||||
|
"dmap.containeritemid", "f.id", 1
|
||||||
"daap.songalbum", "f.album", 0
|
"daap.songalbum", "f.album", 0
|
||||||
"daap.songalbumid", "f.songalbumid", 1
|
"daap.songalbumid", "f.songalbumid", 1
|
||||||
"daap.songartist", "f.album_artist", 0
|
"daap.songartist", "f.album_artist", 0
|
||||||
|
149
src/httpd_dacp.c
149
src/httpd_dacp.c
@ -733,8 +733,8 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
|||||||
{
|
{
|
||||||
sort = evhttp_find_header(query, "sort");
|
sort = evhttp_find_header(query, "sort");
|
||||||
|
|
||||||
ps = player_queue_make_daap(cuequery, sort);
|
ret = player_queue_make_daap(&ps, cuequery, NULL, sort);
|
||||||
if (!ps)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
||||||
|
|
||||||
@ -1238,18 +1238,85 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
|
{
|
||||||
|
struct player_source *ps;
|
||||||
|
const char *editquery;
|
||||||
|
const char *queuefilter;
|
||||||
|
const char *sort;
|
||||||
|
const char *param;
|
||||||
|
uint32_t idx;
|
||||||
|
int mode;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
param = evhttp_find_header(query, "mode");
|
||||||
|
if (param)
|
||||||
|
{
|
||||||
|
ret = safe_atoi32(param, &mode);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DACP, "Invalid mode value in playqueue-edit request\n");
|
||||||
|
|
||||||
|
dmap_send_error(req, "cmst", "Invalid mode value in playqueue-edit request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
{
|
||||||
|
player_playback_stop();
|
||||||
|
player_queue_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
editquery = evhttp_find_header(query, "query");
|
||||||
|
if (editquery)
|
||||||
|
{
|
||||||
|
queuefilter = evhttp_find_header(query, "queuefilter");
|
||||||
|
sort = evhttp_find_header(query, "sort");
|
||||||
|
|
||||||
|
ret = player_queue_make_daap(&ps, editquery, queuefilter, sort);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
||||||
|
|
||||||
|
dmap_send_error(req, "cmst", "Could not build song queue");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = ret;
|
||||||
|
|
||||||
|
player_queue_add(ps);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DACP, "Could not add song queue, DACP query missing\n");
|
||||||
|
|
||||||
|
dmap_send_error(req, "cmst", "Could not add song queue, DACP query missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
param = evhttp_find_header(query, "dacp.shufflestate");
|
||||||
|
if (param)
|
||||||
|
dacp_propset_shufflestate(param, NULL);*/
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_DACP, "Song queue built, playback starting at index %" PRIu32 "\n", idx);
|
||||||
|
ret = player_playback_start(&idx);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
||||||
|
|
||||||
|
dmap_send_error(req, "cmst", "Playback failed to start");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dacp_reply_playqueueedit(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
dacp_reply_playqueueedit(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
struct daap_session *s;
|
struct daap_session *s;
|
||||||
struct player_status status;
|
|
||||||
struct player_source *ps;
|
|
||||||
const char *cuequery;
|
|
||||||
const char *sort;
|
|
||||||
const char *param;
|
const char *param;
|
||||||
uint32_t id;
|
|
||||||
int mode;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Variations of /ctrl-int/1/playqueue-edit and expected behaviour
|
/* Variations of /ctrl-int/1/playqueue-edit and expected behaviour
|
||||||
User selected play (album or artist tab):
|
User selected play (album or artist tab):
|
||||||
@ -1285,64 +1352,26 @@ dacp_reply_playqueueedit(struct evhttp_request *req, struct evbuffer *evbuf, cha
|
|||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
param = evhttp_find_header(query, "mode");
|
param = evhttp_find_header(query, "command");
|
||||||
if (param)
|
if (!param)
|
||||||
{
|
{
|
||||||
ret = safe_atoi32(param, &mode);
|
DPRINTF(E_LOG, L_DACP, "No command in playqueue-edit request\n");
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_DACP, "Invalid mode value in playqueue-edit request\n");
|
|
||||||
else if (mode == 1)
|
|
||||||
{
|
|
||||||
player_playback_stop();
|
|
||||||
|
|
||||||
player_queue_clear();
|
dmap_send_error(req, "cmst", "No command in cue request");
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cuequery = evhttp_find_header(query, "query");
|
if (strcmp(param, "clear") == 0)
|
||||||
if (cuequery)
|
dacp_reply_cue_clear(req, evbuf, uri, query); // TODO this might give wrong reply container
|
||||||
{
|
else if (strcmp(param, "playnow") == 0)
|
||||||
sort = evhttp_find_header(query, "sort");
|
dacp_reply_cue_play(req, evbuf, uri, query); // TODO this might give wrong reply container
|
||||||
|
else if (strcmp(param, "add") == 0)
|
||||||
ps = player_queue_make_daap(cuequery, sort);
|
dacp_reply_playqueueedit_add(req, evbuf, uri, query);
|
||||||
if (!ps)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
|
||||||
|
|
||||||
dmap_send_error(req, "cmst", "Could not build song queue");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player_queue_add(ps);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player_get_status(&status);
|
DPRINTF(E_LOG, L_DACP, "Unknown playqueue-edit command %s\n", param);
|
||||||
|
|
||||||
if (status.status != PLAY_STOPPED)
|
dmap_send_error(req, "cmst", "Unknown command in cue request");
|
||||||
player_playback_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
param = evhttp_find_header(query, "dacp.shufflestate");
|
|
||||||
if (param)
|
|
||||||
dacp_propset_shufflestate(param, NULL);*/
|
|
||||||
|
|
||||||
id = 0;
|
|
||||||
param = evhttp_find_header(query, "index");
|
|
||||||
if (param)
|
|
||||||
{
|
|
||||||
ret = safe_atou32(param, &id);
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_DACP, "Invalid index (%s) in playqueue-edit request\n", param);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = player_playback_start(&id);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
|
||||||
|
|
||||||
dmap_send_error(req, "cmst", "Playback failed to start");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
149
src/player.c
149
src/player.c
@ -635,32 +635,163 @@ player_queue_make(struct query_params *qp, const char *sort)
|
|||||||
return q_head;
|
return q_head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread: httpd (DACP) */
|
static int
|
||||||
struct player_source *
|
fetch_first_query_match(const char *query, struct db_media_file_info *dbmfi)
|
||||||
player_queue_make_daap(const char *query, const char *sort)
|
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct player_source *ps;
|
uint32_t id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
memset(&qp, 0, sizeof(struct query_params));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
qp.type = Q_ITEMS;
|
qp.type = Q_ITEMS;
|
||||||
|
qp.idx_type = I_FIRST;
|
||||||
|
qp.sort = S_NONE;
|
||||||
qp.offset = 0;
|
qp.offset = 0;
|
||||||
qp.limit = 0;
|
qp.limit = 1;
|
||||||
|
|
||||||
qp.filter = daap_query_parse_sql(query);
|
qp.filter = daap_query_parse_sql(query);
|
||||||
if (!qp.filter)
|
if (!qp.filter)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Improper DAAP query!\n");
|
DPRINTF(E_LOG, L_PLAYER, "Improper DAAP query!\n");
|
||||||
|
|
||||||
return NULL;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = db_query_start(&qp);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Could not start query\n");
|
||||||
|
|
||||||
|
goto no_query_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((ret = db_query_fetch_file(&qp, dbmfi)) == 0) && (dbmfi->id))
|
||||||
|
{
|
||||||
|
ret = safe_atou32(dbmfi->id, &id);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Invalid song id in query result!\n");
|
||||||
|
|
||||||
|
goto no_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "Found index song\n");
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "No song matches query (num %d): %s\n", qp.results, qp.filter);
|
||||||
|
|
||||||
|
goto no_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
no_result:
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
|
no_query_start:
|
||||||
|
if (qp.filter)
|
||||||
|
free(qp.filter);
|
||||||
|
if (ret == 1)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Thread: httpd (DACP) */
|
||||||
|
int
|
||||||
|
player_queue_make_daap(struct player_source **head, const char *query, const char *queuefilter, const char *sort)
|
||||||
|
{
|
||||||
|
struct query_params qp;
|
||||||
|
struct player_source *ps;
|
||||||
|
struct db_media_file_info dbmfi;
|
||||||
|
uint32_t id;
|
||||||
|
int64_t albumid;
|
||||||
|
int plid;
|
||||||
|
int idx;
|
||||||
|
int ret;
|
||||||
|
char buf[200];
|
||||||
|
|
||||||
|
/* If query doesn't give even a single result give up */
|
||||||
|
ret = fetch_first_query_match(query, &dbmfi);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
|
qp.offset = 0;
|
||||||
|
qp.limit = 0;
|
||||||
|
|
||||||
|
id = 0;
|
||||||
|
|
||||||
|
if (queuefilter)
|
||||||
|
{
|
||||||
|
safe_atou32(dbmfi.id, &id);
|
||||||
|
if ((strlen(queuefilter) > 6) && (strncmp(queuefilter, "album:", 6) == 0))
|
||||||
|
{
|
||||||
|
qp.type = Q_ITEMS;
|
||||||
|
ret = safe_atoi64(strchr(queuefilter, ':') + 1, &albumid);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Invalid album id in queuefilter: %s\n", queuefilter);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(buf, sizeof(buf), "f.songalbumid = %" PRIi64, albumid);
|
||||||
|
qp.filter = strdup(buf);
|
||||||
|
}
|
||||||
|
else if ((strlen(queuefilter) > 9) && (strncmp(queuefilter, "playlist:", 9) == 0))
|
||||||
|
{
|
||||||
|
qp.type = Q_PLITEMS;
|
||||||
|
ret = safe_atoi32(strchr(queuefilter, ':') + 1, &plid);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Invalid playlist id in queuefilter: %s\n", queuefilter);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
qp.id = plid;
|
||||||
|
qp.filter = strdup("1 = 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Unknown queuefilter: %s\n", queuefilter);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strstr(query, "dmap.itemid:") && dbmfi.album_artist)
|
||||||
|
{
|
||||||
|
safe_atou32(dbmfi.id, &id);
|
||||||
|
qp.type = Q_ITEMS;
|
||||||
|
snprintf(buf, sizeof(buf), "f.album_artist = \"%s\"", dbmfi.album_artist);
|
||||||
|
qp.filter = strdup(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = 0;
|
||||||
|
qp.type = Q_ITEMS;
|
||||||
|
qp.filter = daap_query_parse_sql(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
ps = player_queue_make(&qp, sort);
|
ps = player_queue_make(&qp, sort);
|
||||||
|
|
||||||
free(qp.filter);
|
if (qp.filter)
|
||||||
|
free(qp.filter);
|
||||||
|
|
||||||
return ps;
|
if (ps)
|
||||||
|
*head = ps;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
while (id && ps && ps->pl_next && (ps->id != id) && (ps->pl_next != *head))
|
||||||
|
{
|
||||||
|
idx++;
|
||||||
|
ps = ps->pl_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct player_source *
|
struct player_source *
|
||||||
|
@ -123,9 +123,8 @@ player_repeat_set(enum repeat_mode mode);
|
|||||||
int
|
int
|
||||||
player_shuffle_set(int enable);
|
player_shuffle_set(int enable);
|
||||||
|
|
||||||
|
int
|
||||||
struct player_source *
|
player_queue_make_daap(struct player_source **head, const char *query, const char *queuefilter, const char *sort);
|
||||||
player_queue_make_daap(const char *query, const char *sort);
|
|
||||||
|
|
||||||
struct player_source *
|
struct player_source *
|
||||||
player_queue_make_pl(int plid, uint32_t *id);
|
player_queue_make_pl(int plid, uint32_t *id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user