[library/db/jsonapi] Refactor adding items to queue via JSON API

Reduce code duplication and move database specific stuff from httpd_json.c
to db.c.
This commit is contained in:
ejurgensen 2023-12-03 09:31:36 +01:00
parent cbfce63f4d
commit 1ea90b9445
4 changed files with 126 additions and 210 deletions

View File

@ -5274,33 +5274,6 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id,
return ret;
}
/*
* Adds the items of the stored playlist with the given id to the end of the queue
*
* @param plid Id of the stored playlist
* @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_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id)
{
struct query_params qp;
int ret;
memset(&qp, 0, sizeof(struct query_params));
qp.id = plid;
qp.type = Q_PLITEMS;
ret = db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
return ret;
}
/*
* Adds the file with the given id to the queue
*
@ -5315,19 +5288,54 @@ db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id, int posit
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;
struct query_params qp = { .type = Q_ITEMS, .idx_type = I_NONE };
char buf[124];
int ret;
memset(&qp, 0, sizeof(struct query_params));
qp.type = Q_ITEMS;
snprintf(buf, sizeof(buf), "f.id = %" PRIu32, id);
qp.filter = buf;
ret = db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
return db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id);
}
return ret;
/*
* 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

View File

@ -902,10 +902,16 @@ 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_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
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_fileid(int id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id);
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);

View File

@ -2228,199 +2228,65 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle)
}
static int
queue_tracks_add_artist(const char *id, int pos)
{
struct query_params query_params;
struct player_status status;
int count = 0;
int ret = 0;
memset(&query_params, 0, sizeof(struct query_params));
query_params.type = Q_ITEMS;
query_params.sort = S_ALBUM;
query_params.idx_type = I_NONE;
query_params.filter = db_mprintf("(f.songartistid = %q)", id);
player_get_status(&status);
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL);
free(query_params.filter);
if (ret == 0)
return count;
return ret;
}
static int
queue_tracks_add_album(const char *id, int pos)
{
struct query_params query_params;
struct player_status status;
int count = 0;
int ret = 0;
memset(&query_params, 0, sizeof(struct query_params));
query_params.type = Q_ITEMS;
query_params.sort = S_ALBUM;
query_params.idx_type = I_NONE;
query_params.filter = db_mprintf("(f.songalbumid = %q)", id);
player_get_status(&status);
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL);
free(query_params.filter);
if (ret == 0)
return count;
return ret;
}
static int
queue_tracks_add_track(const char *id, int pos)
{
struct query_params query_params;
struct player_status status;
int count = 0;
int ret = 0;
memset(&query_params, 0, sizeof(struct query_params));
query_params.type = Q_ITEMS;
query_params.sort = S_ALBUM;
query_params.idx_type = I_NONE;
query_params.filter = db_mprintf("(f.id = %q)", id);
player_get_status(&status);
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL);
free(query_params.filter);
if (ret == 0)
return count;
return ret;
}
static int
queue_tracks_add_playlist(const char *id, int pos)
{
struct player_status status;
int playlist_id;
int count = 0;
int ret;
ret = safe_atoi32(id, &playlist_id);
if (ret < 0)
{
DPRINTF(E_LOG, L_WEB, "No valid playlist id given '%s'\n", id);
return HTTP_BADREQUEST;
}
player_get_status(&status);
ret = db_queue_add_by_playlistid(playlist_id, status.shuffle, status.item_id, pos, &count, NULL);
if (ret == 0)
return count;
return ret;
}
static int
queue_tracks_add_byuris(const char *param, int pos, int *total_count)
queue_tracks_add_byuris(const char *param, int pos, int *total_count, int *new_item_id)
{
struct player_status status;
char *uris;
char *uri;
const char *uri;
char *ptr;
const char *id;
int count = 0;
int ret = 0;
int count;
int new;
int ret;
*total_count = 0;
*new_item_id = -1;
CHECK_NULL(L_WEB, uris = strdup(param));
uri = strtok_r(uris, ",", &ptr);
uri = strtok_r(uris, ",", &ptr);
if (!uri)
{
DPRINTF(E_LOG, L_WEB, "Empty query parameter 'uris'\n");
free(uris);
return -1;
goto error;
}
do
player_get_status(&status);
for (; uri; uri = strtok_r(NULL, ",", &ptr))
{
count = 0;
if (strncmp(uri, "library:artist:", strlen("library:artist:")) == 0)
ret = library_queue_item_add(uri, pos, status.shuffle, status.item_id, &count, &new);
if (ret != LIBRARY_OK)
{
id = uri + (strlen("library:artist:"));
count = queue_tracks_add_artist(id, pos);
}
else if (strncmp(uri, "library:album:", strlen("library:album:")) == 0)
{
id = uri + (strlen("library:album:"));
count = queue_tracks_add_album(id, pos);
}
else if (strncmp(uri, "library:track:", strlen("library:track:")) == 0)
{
id = uri + (strlen("library:track:"));
count = queue_tracks_add_track(id, pos);
}
else if (strncmp(uri, "library:playlist:", strlen("library:playlist:")) == 0)
{
id = uri + (strlen("library:playlist:"));
count = queue_tracks_add_playlist(id, pos);
}
else
{
player_get_status(&status);
ret = library_queue_item_add(uri, pos, status.shuffle, status.item_id, &count, NULL);
if (ret != LIBRARY_OK)
{
DPRINTF(E_LOG, L_WEB, "Invalid uri '%s'\n", uri);
break;
}
pos += count;
DPRINTF(E_LOG, L_WEB, "Invalid uri '%s'\n", uri);
goto error;
}
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);
}
while ((uri = strtok_r(NULL, ",", &ptr)));
free(uris);
return 0;
return ret;
error:
free(uris);
return -1;
}
static int
queue_tracks_add_byexpression(const char *param, int pos, int limit, int *total_count)
queue_tracks_add_byexpression(const char *param, 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 smartpl smartpl_expression;
struct query_params query_params;
struct player_status status;
int ret;
memset(&query_params, 0, sizeof(struct query_params));
query_params.type = Q_ITEMS;
query_params.sort = S_NAME;
memset(&smartpl_expression, 0, sizeof(struct smartpl));
expression = safe_asprintf("\"query\" { %s }", param);
ret = smartpl_query_parse_string(&smartpl_expression, expression);
free(expression);
@ -2431,18 +2297,15 @@ queue_tracks_add_byexpression(const char *param, int pos, int limit, int *total_
query_params.filter = strdup(smartpl_expression.query_where);
query_params.order = safe_strdup(smartpl_expression.order);
query_params.limit = limit > 0 ? limit : smartpl_expression.limit;
query_params.idx_type = query_params.limit > 0 ? I_FIRST : I_NONE;
free_smartpl(&smartpl_expression, 1);
player_get_status(&status);
query_params.idx_type = query_params.limit > 0 ? I_FIRST : I_NONE;
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, total_count, NULL);
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, total_count, new_item_id);
free_query_params(&query_params, 1);
return ret;
}
static int
@ -2456,6 +2319,7 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
int limit;
bool shuffle;
int total_count = 0;
int new_item_id = 0;
json_object *reply;
int ret = 0;
@ -2470,7 +2334,7 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
return HTTP_BADREQUEST;
}
DPRINTF(E_DBG, L_WEB, "Add tracks starting at position '%d\n", pos);
DPRINTF(E_DBG, L_WEB, "Add tracks starting at position %d\n", pos);
}
else
pos = -1;
@ -2503,16 +2367,16 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
if (param_uris)
{
ret = queue_tracks_add_byuris(param_uris, pos, &total_count);
ret = queue_tracks_add_byuris(param_uris, 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);
ret = queue_tracks_add_byexpression(param_expression, pos, limit, &total_count, &new_item_id);
else
ret = queue_tracks_add_byexpression(param_expression, pos, -1, &total_count);
ret = queue_tracks_add_byexpression(param_expression, pos, -1, &total_count, &new_item_id);
}
if (ret == 0)

View File

@ -1719,6 +1719,41 @@ filescanner_fullrescan()
return 0;
}
static int
queue_item_file_add(const char *sub_uri, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
{
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);
}
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);
}
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);
}
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);
}
else
{
return -1;
}
}
static int
queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
{
@ -1758,13 +1793,16 @@ queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t i
static int
queue_item_add(const char *uri, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
{
if (net_is_http_or_https(uri))
{
queue_item_stream_add(uri, position, reshuffle, item_id, count, new_item_id);
return LIBRARY_OK;
}
int ret;
return LIBRARY_PATH_INVALID;
if (strncmp(uri, "library:", strlen("library:")) == 0)
ret = queue_item_file_add(uri + strlen("library:"), position, reshuffle, item_id, count, new_item_id);
else if (net_is_http_or_https(uri))
ret = queue_item_stream_add(uri, position, reshuffle, item_id, count, new_item_id);
else
ret = -1;
return (ret == 0) ? LIBRARY_OK : LIBRARY_PATH_INVALID;
}
static const char *