Skip to content

Commit

Permalink
[library/db/jsonapi] Refactor adding items to queue via JSON API v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ejurgensen committed Dec 17, 2023
1 parent 1ea90b9 commit 5ea49c9
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 120 deletions.
83 changes: 17 additions & 66 deletions src/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
{
Expand Down
12 changes: 0 additions & 12 deletions src/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions src/httpd_dacp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
64 changes: 36 additions & 28 deletions src/httpd_jsonapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -2300,27 +2294,45 @@ 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)
{
const char *param_pos;
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;


Expand Down Expand Up @@ -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;

Expand Down
6 changes: 4 additions & 2 deletions src/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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, &param);
}
Expand Down
21 changes: 17 additions & 4 deletions src/library/filescanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/mpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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], ":/"))
Expand All @@ -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]);
Expand Down
Loading

0 comments on commit 5ea49c9

Please sign in to comment.