mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-26 22:23:17 -05:00
[library/db/jsonapi] Refactor adding items to queue via JSON API v2
This commit is contained in:
parent
1ea90b9445
commit
5ea49c94de
83
src/db.c
83
src/db.c
@ -1969,6 +1969,8 @@ db_free_query_clause(struct query_clause *qc)
|
||||
free(qc);
|
||||
}
|
||||
|
||||
// Builds the generic parts of the query. Parts that are specific to the query
|
||||
// type are in db_build_query_* implementations.
|
||||
static struct query_clause *
|
||||
db_build_query_clause(struct query_params *qp)
|
||||
{
|
||||
@ -2076,8 +2078,21 @@ db_build_query_items(struct query_params *qp, struct query_clause *qc)
|
||||
char *count;
|
||||
char *query;
|
||||
|
||||
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s;", qc->where);
|
||||
query = sqlite3_mprintf("SELECT f.* FROM files f %s %s %s %s;", qc->where, qc->group, qc->order, qc->index);
|
||||
if (qp->id == 0)
|
||||
{
|
||||
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s;", qc->where);
|
||||
query = sqlite3_mprintf("SELECT f.* FROM files f %s %s %s %s;", qc->where, qc->group, qc->order, qc->index);
|
||||
}
|
||||
else if (qc->where[0] == '\0')
|
||||
{
|
||||
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.id = %d;", qp->id);
|
||||
query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.id = %d %s %s %s;", qp->id, qc->group, qc->order, qc->index);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND f.id = %d;", qc->where, qp->id);
|
||||
query = sqlite3_mprintf("SELECT f.* FROM files f %s AND f.id = %d %s %s %s;", qc->where, qp->id, qc->group, qc->order, qc->index);
|
||||
}
|
||||
|
||||
return db_build_query_check(qp, count, query);
|
||||
}
|
||||
@ -5274,70 +5289,6 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the file with the given id to the queue
|
||||
*
|
||||
* @param id Id of the file
|
||||
* @param reshuffle If 1 queue will be reshuffled after adding new items
|
||||
* @param item_id The base item id, all items after this will be reshuffled
|
||||
* @param position The position in the queue for the new queue item, -1 to add at end of queue
|
||||
* @param count If not NULL returns the number of items added to the queue
|
||||
* @param new_item_id If not NULL return the queue item id of the first new queue item
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id)
|
||||
{
|
||||
struct query_params qp = { .type = Q_ITEMS, .idx_type = I_NONE };
|
||||
char buf[124];
|
||||
|
||||
snprintf(buf, sizeof(buf), "f.id = %" PRIu32, id);
|
||||
qp.filter = buf;
|
||||
|
||||
return db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the artist with the given id to the queue, see db_queue_add_by_fileid()
|
||||
*/
|
||||
int
|
||||
db_queue_add_by_artistid(int64_t id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id)
|
||||
{
|
||||
struct query_params qp = { .type = Q_ITEMS, .idx_type = I_NONE, .sort = S_ALBUM };
|
||||
char buf[124];
|
||||
|
||||
snprintf(buf, sizeof(buf), "f.songartistid = %" PRIi64, id);
|
||||
qp.filter = buf;
|
||||
|
||||
return db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the artist with the given id to the queue, see db_queue_add_by_fileid()
|
||||
*/
|
||||
int
|
||||
db_queue_add_by_albumid(int64_t id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id)
|
||||
{
|
||||
struct query_params qp = { .type = Q_ITEMS, .idx_type = I_NONE, .sort = S_ALBUM };
|
||||
char buf[124];
|
||||
|
||||
snprintf(buf, sizeof(buf), "f.songalbumid = %" PRIi64, id);
|
||||
qp.filter = buf;
|
||||
|
||||
return db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the playlist with the given id to the queue, see db_queue_add_by_fileid()
|
||||
*/
|
||||
int
|
||||
db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id)
|
||||
{
|
||||
struct query_params qp = { .type = Q_PLITEMS, .id = plid };
|
||||
|
||||
return db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
|
||||
}
|
||||
|
||||
static int
|
||||
queue_enum_start(struct query_params *qp)
|
||||
{
|
||||
|
12
src/db.h
12
src/db.h
@ -901,18 +901,6 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id);
|
||||
int
|
||||
db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
|
||||
|
||||
int
|
||||
db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
|
||||
|
||||
int
|
||||
db_queue_add_by_artistid(int64_t songartistid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
|
||||
|
||||
int
|
||||
db_queue_add_by_albumid(int64_t songalbumid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
|
||||
|
||||
int
|
||||
db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
|
||||
|
||||
int
|
||||
db_queue_add_start(struct db_queue_add_info *queue_add_info, int pos);
|
||||
|
||||
|
@ -1397,6 +1397,7 @@ dacp_reply_playspec(struct httpd_request *hreq)
|
||||
const char *shuffle;
|
||||
uint32_t plid;
|
||||
uint32_t id;
|
||||
struct query_params qp = { 0 };
|
||||
struct db_queue_item *queue_item = NULL;
|
||||
int ret;
|
||||
|
||||
@ -1482,11 +1483,10 @@ dacp_reply_playspec(struct httpd_request *hreq)
|
||||
|
||||
db_queue_clear(0);
|
||||
|
||||
if (plid > 0)
|
||||
ret = db_queue_add_by_playlistid(plid, status.shuffle, status.item_id, -1, NULL, NULL);
|
||||
else if (id > 0)
|
||||
ret = db_queue_add_by_fileid(id, status.shuffle, status.item_id, -1, NULL, NULL);
|
||||
qp.type = (plid > 0) ? Q_PLITEMS : Q_ITEMS;
|
||||
qp.id = (plid > 0) ? plid : id;
|
||||
|
||||
ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, -1, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue from playlist %d\n", plid);
|
||||
|
@ -2228,9 +2228,8 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle)
|
||||
}
|
||||
|
||||
static int
|
||||
queue_tracks_add_byuris(const char *param, int pos, int *total_count, int *new_item_id)
|
||||
queue_tracks_add_byuris(const char *param, char shuffle, uint32_t item_id, int pos, int *total_count, int *new_item_id)
|
||||
{
|
||||
struct player_status status;
|
||||
char *uris;
|
||||
const char *uri;
|
||||
char *ptr;
|
||||
@ -2250,24 +2249,20 @@ queue_tracks_add_byuris(const char *param, int pos, int *total_count, int *new_i
|
||||
goto error;
|
||||
}
|
||||
|
||||
player_get_status(&status);
|
||||
|
||||
for (; uri; uri = strtok_r(NULL, ",", &ptr))
|
||||
{
|
||||
ret = library_queue_item_add(uri, pos, status.shuffle, status.item_id, &count, &new);
|
||||
ret = library_queue_item_add(uri, pos, shuffle, item_id, &count, &new);
|
||||
if (ret != LIBRARY_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Invalid uri '%s'\n", uri);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*total_count += count;
|
||||
if (pos >= 0)
|
||||
pos += count;
|
||||
|
||||
*new_item_id = (*new_item_id == -1) ? new : MIN(*new_item_id, new);
|
||||
*total_count += count;
|
||||
|
||||
DPRINTF(E_DBG, L_WEB, "pos %d, count %d, new %d, new_item_id %d\n", pos, count, new, *new_item_id);
|
||||
if (*new_item_id == -1)
|
||||
*new_item_id = new;
|
||||
}
|
||||
|
||||
free(uris);
|
||||
@ -2279,12 +2274,11 @@ queue_tracks_add_byuris(const char *param, int pos, int *total_count, int *new_i
|
||||
}
|
||||
|
||||
static int
|
||||
queue_tracks_add_byexpression(const char *param, int pos, int limit, int *total_count, int *new_item_id)
|
||||
queue_tracks_add_byexpression(const char *param, char shuffle, uint32_t item_id, int pos, int limit, int *total_count, int *new_item_id)
|
||||
{
|
||||
struct query_params query_params = { .type = Q_ITEMS, .sort = S_NAME };
|
||||
struct smartpl smartpl_expression = { 0 };
|
||||
char *expression;
|
||||
struct player_status status;
|
||||
int ret;
|
||||
|
||||
expression = safe_asprintf("\"query\" { %s }", param);
|
||||
@ -2300,14 +2294,32 @@ queue_tracks_add_byexpression(const char *param, int pos, int limit, int *total_
|
||||
query_params.idx_type = query_params.limit > 0 ? I_FIRST : I_NONE;
|
||||
free_smartpl(&smartpl_expression, 1);
|
||||
|
||||
player_get_status(&status);
|
||||
|
||||
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, total_count, new_item_id);
|
||||
ret = db_queue_add_by_query(&query_params, shuffle, item_id, pos, total_count, new_item_id);
|
||||
|
||||
free_query_params(&query_params, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
create_reply_queue_tracks_add(struct evbuffer *evbuf, int count, int new_item_id, char shuffle)
|
||||
{
|
||||
json_object *reply = json_object_new_object();
|
||||
int ret;
|
||||
|
||||
json_object_object_add(reply, "count", json_object_new_int(count));
|
||||
|
||||
ret = evbuffer_add_printf(evbuf, "%s", json_object_to_json_string(reply));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
jparse_free(reply);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
jparse_free(reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
{
|
||||
@ -2315,12 +2327,12 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
const char *param_uris;
|
||||
const char *param_expression;
|
||||
const char *param;
|
||||
struct player_status status;
|
||||
int pos;
|
||||
int limit;
|
||||
bool shuffle;
|
||||
int total_count = 0;
|
||||
int new_item_id = 0;
|
||||
json_object *reply;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
@ -2365,29 +2377,25 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
player_shuffle_set(shuffle);
|
||||
}
|
||||
|
||||
player_get_status(&status);
|
||||
|
||||
if (param_uris)
|
||||
{
|
||||
ret = queue_tracks_add_byuris(param_uris, pos, &total_count, &new_item_id);
|
||||
ret = queue_tracks_add_byuris(param_uris, status.shuffle, status.item_id, pos, &total_count, &new_item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This overrides the value specified in query
|
||||
param = httpd_query_value_find(hreq->query, "limit");
|
||||
if (param && safe_atoi32(param, &limit) == 0)
|
||||
ret = queue_tracks_add_byexpression(param_expression, pos, limit, &total_count, &new_item_id);
|
||||
ret = queue_tracks_add_byexpression(param_expression, status.shuffle, status.item_id, pos, limit, &total_count, &new_item_id);
|
||||
else
|
||||
ret = queue_tracks_add_byexpression(param_expression, pos, -1, &total_count, &new_item_id);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
reply = json_object_new_object();
|
||||
json_object_object_add(reply, "count", json_object_new_int(total_count));
|
||||
|
||||
ret = evbuffer_add_printf(hreq->out_body, "%s", json_object_to_json_string(reply));
|
||||
jparse_free(reply);
|
||||
ret = queue_tracks_add_byexpression(param_expression, status.shuffle, status.item_id, pos, -1, &total_count, &new_item_id);
|
||||
}
|
||||
if (ret < 0)
|
||||
return HTTP_INTERNAL;
|
||||
|
||||
ret = create_reply_queue_tracks_add(hreq->out_body, total_count, new_item_id, status.shuffle);
|
||||
if (ret < 0)
|
||||
return HTTP_INTERNAL;
|
||||
|
||||
|
@ -842,6 +842,8 @@ int
|
||||
library_queue_item_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
|
||||
{
|
||||
struct queue_item_add_param param;
|
||||
int count_internal;
|
||||
int new_item_id_internal;
|
||||
|
||||
if (library_is_scanning())
|
||||
return -1;
|
||||
@ -850,8 +852,8 @@ library_queue_item_add(const char *path, int position, char reshuffle, uint32_t
|
||||
param.position = position;
|
||||
param.reshuffle = reshuffle;
|
||||
param.item_id = item_id;
|
||||
param.count = count;
|
||||
param.new_item_id = new_item_id;
|
||||
param.count = count ? count : &count_internal;
|
||||
param.new_item_id = new_item_id ? new_item_id : &new_item_id_internal;
|
||||
|
||||
return commands_exec_sync(cmdbase, queue_item_add, NULL, ¶m);
|
||||
}
|
||||
|
@ -1722,36 +1722,49 @@ filescanner_fullrescan()
|
||||
static int
|
||||
queue_item_file_add(const char *sub_uri, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
|
||||
{
|
||||
struct query_params query_params = { 0 };
|
||||
int64_t id;
|
||||
|
||||
if (strncmp(sub_uri, "artist:", strlen("artist:")) == 0)
|
||||
{
|
||||
if (safe_atoi64(sub_uri + (strlen("artist:")), &id) < 0)
|
||||
return -1;
|
||||
return db_queue_add_by_artistid(id, reshuffle, item_id, position, count, new_item_id);
|
||||
|
||||
query_params.type = Q_GROUP_ITEMS;
|
||||
query_params.sort = S_ALBUM;
|
||||
query_params.persistentid = id;
|
||||
}
|
||||
else if (strncmp(sub_uri, "album:", strlen("album:")) == 0)
|
||||
{
|
||||
if (safe_atoi64(sub_uri + (strlen("album:")), &id) < 0)
|
||||
return -1;
|
||||
return db_queue_add_by_albumid(id, reshuffle, item_id, position, count, new_item_id);
|
||||
|
||||
query_params.type = Q_GROUP_ITEMS;
|
||||
query_params.sort = S_ALBUM;
|
||||
query_params.persistentid = id;
|
||||
}
|
||||
else if (strncmp(sub_uri, "track:", strlen("track:")) == 0)
|
||||
{
|
||||
if (safe_atoi64(sub_uri + (strlen("track:")), &id) < 0)
|
||||
return -1;
|
||||
return db_queue_add_by_fileid((int)id, reshuffle, item_id, position, count, new_item_id);
|
||||
|
||||
query_params.type = Q_ITEMS;
|
||||
query_params.id = id;
|
||||
}
|
||||
else if (strncmp(sub_uri, "playlist:", strlen("playlist:")) == 0)
|
||||
{
|
||||
if (safe_atoi64(sub_uri + (strlen("playlist:")), &id) < 0)
|
||||
return -1;
|
||||
return db_queue_add_by_playlistid((int)id, reshuffle, item_id, position, count, new_item_id);
|
||||
|
||||
query_params.type = Q_PLITEMS;
|
||||
query_params.id = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return db_queue_add_by_query(&query_params, reshuffle, item_id, position, count, new_item_id);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2461,6 +2461,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, s
|
||||
char *path;
|
||||
struct playlist_info *pli;
|
||||
struct player_status status;
|
||||
struct query_params qp = { .type = Q_PLITEMS };
|
||||
int ret;
|
||||
|
||||
if (!default_pl_dir || strstr(argv[1], ":/"))
|
||||
@ -2484,10 +2485,12 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, s
|
||||
|
||||
//TODO If a second parameter is given only add the specified range of songs to the playqueue
|
||||
|
||||
qp.id = pli->id;
|
||||
free_pli(pli, 0);
|
||||
|
||||
player_get_status(&status);
|
||||
|
||||
ret = db_queue_add_by_playlistid(pli->id, status.shuffle, status.item_id, -1, NULL, NULL);
|
||||
free_pli(pli, 0);
|
||||
ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, -1, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Failed to add song '%s' to playlist", argv[1]);
|
||||
|
@ -2118,9 +2118,11 @@ playback_start_item(void *arg, int *retval)
|
||||
static enum command_state
|
||||
playback_start_id(void *arg, int *retval)
|
||||
{
|
||||
struct query_params qp = { .type = Q_ITEMS };
|
||||
struct db_queue_item *queue_item = NULL;
|
||||
union player_arg *cmdarg = arg;
|
||||
enum command_state cmd_state;
|
||||
int new_item_id;
|
||||
int ret;
|
||||
|
||||
*retval = -1;
|
||||
@ -2129,11 +2131,13 @@ playback_start_id(void *arg, int *retval)
|
||||
{
|
||||
db_queue_clear(0);
|
||||
|
||||
ret = db_queue_add_by_fileid(cmdarg->id, 0, 0, -1, NULL, NULL);
|
||||
qp.id = cmdarg->id;
|
||||
|
||||
ret = db_queue_add_by_query(&qp, 0, 0, -1, NULL, &new_item_id);
|
||||
if (ret < 0)
|
||||
return COMMAND_END;
|
||||
|
||||
queue_item = db_queue_fetch_byfileid(cmdarg->id);
|
||||
queue_item = db_queue_fetch_byitemid(new_item_id);
|
||||
if (!queue_item)
|
||||
return COMMAND_END;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user