mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 23:55:57 -05:00
[queue] Refactor queue handling
Decouple the playing/streaming item from the queue. Move all queue related functions to seperate file queue.h/c. Introduce internal item "head" to make iterating over the play-queue and shuffle-queue easier.
This commit is contained in:
parent
10d7097f98
commit
1f53d7ab1a
@ -102,6 +102,7 @@ forked_daapd_SOURCES = main.c \
|
||||
rsp_query.c rsp_query.h \
|
||||
daap_query.c daap_query.h \
|
||||
player.c player.h \
|
||||
queue.c queue.h \
|
||||
worker.c worker.h \
|
||||
$(ALSA_SRC) $(OSS4_SRC) \
|
||||
laudio_dummy.c \
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "db.h"
|
||||
#include "daap_query.h"
|
||||
#include "player.h"
|
||||
#include "queue.h"
|
||||
#include "listener.h"
|
||||
|
||||
/* httpd event base, from httpd.c */
|
||||
@ -757,6 +758,7 @@ dacp_reply_ctrlint(struct evhttp_request *req, struct evbuffer *evbuf, char **ur
|
||||
static int
|
||||
find_first_song_id(const char *query)
|
||||
{
|
||||
//TODO [refactor][performance] Unnecessary query, it is enough to extract the item id from the query string. Accessing the db to verify the item exists is not needed.
|
||||
struct db_media_file_info dbmfi;
|
||||
struct query_params qp;
|
||||
int id;
|
||||
@ -821,11 +823,11 @@ find_first_song_id(const char *query)
|
||||
|
||||
|
||||
static int
|
||||
make_queue_for_query(struct player_source **head, const char *query, const char *queuefilter, const char *sort, int quirk)
|
||||
make_queue_for_query(struct queue_item **head, const char *query, const char *queuefilter, const char *sort, int quirk)
|
||||
{
|
||||
struct media_file_info *mfi;
|
||||
struct query_params qp;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
int64_t albumid;
|
||||
int64_t artistid;
|
||||
int plid;
|
||||
@ -941,22 +943,18 @@ make_queue_for_query(struct player_source **head, const char *query, const char
|
||||
qp.sort = S_ARTIST;
|
||||
}
|
||||
|
||||
ps = player_queue_make(&qp);
|
||||
items = queue_make(&qp);
|
||||
|
||||
if (qp.filter)
|
||||
free(qp.filter);
|
||||
|
||||
if (ps)
|
||||
*head = ps;
|
||||
if (items)
|
||||
*head = items;
|
||||
else
|
||||
return -1;
|
||||
|
||||
idx = 0;
|
||||
while (id && ps && ps->pl_next && (ps->id != id) && (ps->pl_next != *head))
|
||||
{
|
||||
idx++;
|
||||
ps = ps->pl_next;
|
||||
}
|
||||
// Get the position (0-based) of the first item
|
||||
idx = queueitem_pos(items, id);
|
||||
|
||||
return idx;
|
||||
}
|
||||
@ -965,7 +963,7 @@ static void
|
||||
dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||
{
|
||||
struct player_status status;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
const char *sort;
|
||||
const char *cuequery;
|
||||
const char *param;
|
||||
@ -997,7 +995,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
sort = evhttp_find_header(query, "sort");
|
||||
|
||||
ret = make_queue_for_query(&ps, cuequery, NULL, sort, 0);
|
||||
ret = make_queue_for_query(&items, cuequery, NULL, sort, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
||||
@ -1006,7 +1004,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
return;
|
||||
}
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1063,9 +1061,9 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
|
||||
/* If playing from history queue, the pos holds the id of the item to play */
|
||||
if (hist)
|
||||
ret = player_playback_startid(id, &id);
|
||||
ret = player_playback_start_byitemid(id, &id);
|
||||
else
|
||||
ret = player_playback_startpos(pos, &id);
|
||||
ret = player_playback_start_bypos(pos, &id);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -1134,7 +1132,7 @@ static void
|
||||
dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||
{
|
||||
struct player_status status;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
struct daap_session *s;
|
||||
const char *param;
|
||||
const char *shuffle;
|
||||
@ -1216,8 +1214,8 @@ dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
|
||||
DPRINTF(E_DBG, L_DACP, "Playspec request for playlist %d, start song id %d%s\n", plid, pos, (shuffle) ? ", shuffle" : "");
|
||||
|
||||
ps = player_queue_make_pl(plid, &pos);
|
||||
if (!ps)
|
||||
items = queue_make_pl(plid); //TODO [queue] get queue-item-id or pos for first song to play (dacp) --- , &pos);
|
||||
if (!items)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue from playlist %d\n", plid);
|
||||
|
||||
@ -1232,13 +1230,13 @@ dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
player_playback_stop();
|
||||
|
||||
player_queue_clear();
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
player_queue_plid(plid);
|
||||
|
||||
if (shuffle)
|
||||
dacp_propset_shufflestate(shuffle, NULL);
|
||||
|
||||
ret = player_playback_startpos(pos, &id);
|
||||
ret = player_playback_start_bypos(pos, &id);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
||||
@ -1472,7 +1470,7 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
struct evbuffer *playlists;
|
||||
struct player_status status;
|
||||
struct player_history *history;
|
||||
struct player_queue *queue;
|
||||
struct queue_info *queue;
|
||||
const char *param;
|
||||
size_t songlist_length;
|
||||
size_t playlist_length;
|
||||
@ -1544,13 +1542,13 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
/* Get queue and make songlist only if playing or paused */
|
||||
if (status.status != PLAY_STOPPED)
|
||||
{
|
||||
queue = player_queue_get_relative(abs(span));
|
||||
queue = player_queue_get_bypos(abs(span));
|
||||
if (queue)
|
||||
{
|
||||
i = queue->start_pos;
|
||||
for (n = 0; (n < queue->count) && (n < abs(span)); n++)
|
||||
{
|
||||
ret = playqueuecontents_add_source(songlist, queue->queue[n], (n + i + 1), status.plid);
|
||||
ret = playqueuecontents_add_source(songlist, queue->queue[n].dbmfi_id, (n + i + 1), status.plid);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n");
|
||||
@ -1559,8 +1557,8 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
return;
|
||||
}
|
||||
}
|
||||
queue_info_free(queue);
|
||||
}
|
||||
queue_free(queue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1644,9 +1642,7 @@ static void
|
||||
dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||
{
|
||||
const char *param;
|
||||
int clear_hist;
|
||||
|
||||
clear_hist = 0;
|
||||
param = evhttp_find_header(query, "mode");
|
||||
|
||||
/*
|
||||
@ -1655,9 +1651,9 @@ dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbu
|
||||
* otherwise the current playlist.
|
||||
*/
|
||||
if (strcmp(param,"0x68697374") == 0)
|
||||
clear_hist = 1;
|
||||
|
||||
player_queue_empty(clear_hist);
|
||||
player_queue_clear_history();
|
||||
else
|
||||
player_queue_clear();
|
||||
|
||||
dmap_add_container(evbuf, "cacr", 24); /* 8 + len */
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
@ -1678,7 +1674,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
//?command=add&query='dmap.itemid:2'&query-modifier=containers&sort=name&mode=2&session-id=100
|
||||
// -> mode 2: stop playblack, clear playqueue, add shuffled songs from playlist=itemid to playqueue
|
||||
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
const char *editquery;
|
||||
const char *queuefilter;
|
||||
const char *querymodifier;
|
||||
@ -1730,7 +1726,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
if (!querymodifier || (strcmp(querymodifier, "containers") != 0))
|
||||
{
|
||||
quirkyquery = (mode == 1) && strstr(editquery, "dmap.itemid:") && ((!queuefilter) || strstr(queuefilter, "(null)"));
|
||||
ret = make_queue_for_query(&ps, editquery, queuefilter, sort, quirkyquery);
|
||||
ret = make_queue_for_query(&items, editquery, queuefilter, sort, quirkyquery);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1745,7 +1741,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
}
|
||||
|
||||
snprintf(modifiedquery, sizeof(modifiedquery), "playlist:%d", plid);
|
||||
ret = make_queue_for_query(&ps, NULL, modifiedquery, sort, 0);
|
||||
ret = make_queue_for_query(&items, NULL, modifiedquery, sort, 0);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
@ -1760,11 +1756,11 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
|
||||
if (mode == 3)
|
||||
{
|
||||
player_queue_add_next(ps);
|
||||
player_queue_add_next(items);
|
||||
}
|
||||
else
|
||||
{
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1782,7 +1778,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_DACP, "Song queue built, playback starting at index %" PRIu32 "\n", idx);
|
||||
ret = player_playback_startpos(idx, NULL);
|
||||
ret = player_playback_start_bypos(idx, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
||||
@ -1833,7 +1829,7 @@ dacp_reply_playqueueedit_move(struct evhttp_request *req, struct evbuffer *evbuf
|
||||
return;
|
||||
}
|
||||
|
||||
player_queue_move(src, dst);
|
||||
player_queue_move_bypos(src, dst);
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
@ -1865,7 +1861,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb
|
||||
return;
|
||||
}
|
||||
|
||||
player_queue_remove_pos_relative(item_index);
|
||||
player_queue_remove_bypos(item_index);
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
|
101
src/mpd.c
101
src/mpd.c
@ -57,6 +57,7 @@
|
||||
#include "artwork.h"
|
||||
|
||||
#include "player.h"
|
||||
#include "queue.h"
|
||||
#include "filescanner.h"
|
||||
|
||||
|
||||
@ -1210,7 +1211,7 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
}
|
||||
|
||||
if (songpos > 0)
|
||||
ret = player_playback_startpos(songpos, NULL);
|
||||
ret = player_playback_start_byindex(songpos, NULL);
|
||||
else
|
||||
ret = player_playback_start(NULL);
|
||||
|
||||
@ -1263,7 +1264,7 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
}
|
||||
|
||||
if (id > 0)
|
||||
ret = player_playback_startid(id, NULL);
|
||||
ret = player_playback_start_byitemid(id, NULL);
|
||||
else
|
||||
ret = player_playback_start(NULL);
|
||||
|
||||
@ -1506,11 +1507,11 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct player_source *
|
||||
static struct queue_item *
|
||||
make_queue_for_path(char *path, int recursive)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
@ -1531,10 +1532,10 @@ make_queue_for_path(char *path, int recursive)
|
||||
DPRINTF(E_DBG, L_PLAYER, "Out of memory\n");
|
||||
}
|
||||
|
||||
ps = player_queue_make(&qp);
|
||||
items = queue_make(&qp);
|
||||
|
||||
sqlite3_free(qp.filter);
|
||||
return ps;
|
||||
return items;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1545,7 +1546,7 @@ make_queue_for_path(char *path, int recursive)
|
||||
static int
|
||||
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
int ret;
|
||||
|
||||
if (argc < 2)
|
||||
@ -1556,9 +1557,9 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ps = make_queue_for_path(argv[1], 1);
|
||||
items = make_queue_for_path(argv[1], 1);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||
if (ret < 0)
|
||||
@ -1566,7 +1567,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
|
||||
ret = player_playback_start(NULL);
|
||||
if (ret < 0)
|
||||
@ -1586,7 +1587,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
static int
|
||||
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
int ret;
|
||||
|
||||
if (argc < 2)
|
||||
@ -1603,9 +1604,9 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
DPRINTF(E_LOG, L_MPD, "Adding at a specified position not supported for 'addid', adding songs at end of queue.\n");
|
||||
}
|
||||
|
||||
ps = make_queue_for_path(argv[1], 0);
|
||||
items = make_queue_for_path(argv[1], 0);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||
if (ret < 0)
|
||||
@ -1614,13 +1615,14 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
}
|
||||
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
|
||||
//TODO [queue] Get queue-item-id for mpd-command addid
|
||||
evbuffer_add_printf(evbuf,
|
||||
"addid: %s\n"
|
||||
"Id: %d\n",
|
||||
argv[1],
|
||||
ps->id);
|
||||
0); //ps->id);
|
||||
|
||||
ret = player_playback_start(NULL);
|
||||
if (ret < 0)
|
||||
@ -1668,7 +1670,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
// If argv[1] is ommited clear the whole queue except the current playing one
|
||||
if (argc < 2)
|
||||
{
|
||||
player_queue_empty(0);
|
||||
player_queue_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1695,7 +1697,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ret = player_queue_remove_pos_relative(pos);
|
||||
ret = player_queue_remove_bypos(pos);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to remove song at position '%d'", pos);
|
||||
@ -1734,7 +1736,7 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ret = player_queue_remove_queueitemid(songid);
|
||||
ret = player_queue_remove_byitemid(songid);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to remove song with id '%s'", argv[1]);
|
||||
@ -1756,7 +1758,7 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
||||
static int
|
||||
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct player_queue *queue;
|
||||
struct queue_info *queue;
|
||||
uint32_t songid;
|
||||
int pos_pl;
|
||||
int i;
|
||||
@ -1777,7 +1779,7 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
||||
}
|
||||
|
||||
// Get the whole queue (start_pos = 0, end_pos = -1)
|
||||
queue = player_queue_get(0, 0);
|
||||
queue = player_queue_get_byindex(0, 0);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1788,14 +1790,14 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
{
|
||||
if (songid == 0 || songid == queue->queue[i])
|
||||
if (songid == 0 || songid == queue->queue[i].item_id)
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i].dbmfi_id, pos_pl);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i]);
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i].dbmfi_id);
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||
@ -1806,7 +1808,7 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
||||
pos_pl++;
|
||||
}
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1822,7 +1824,7 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
||||
static int
|
||||
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct player_queue *queue;
|
||||
struct queue_info *queue;
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
int count;
|
||||
@ -1854,7 +1856,7 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
count = 0;
|
||||
}
|
||||
|
||||
queue = player_queue_get(start_pos, count);
|
||||
queue = player_queue_get_byindex(start_pos, count);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1865,12 +1867,12 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i].dbmfi_id, pos_pl);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i]);
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i].dbmfi_id);
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||
@ -1880,7 +1882,7 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
pos_pl++;
|
||||
}
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1892,7 +1894,7 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
static int
|
||||
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct player_queue *queue;
|
||||
struct queue_info *queue;
|
||||
int pos_pl;
|
||||
int i;
|
||||
int ret;
|
||||
@ -1901,7 +1903,7 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
* forked-daapd does not keep track of changes in the queue based on the playlist version,
|
||||
* therefor plchanges returns all songs in the queue as changed ignoring the given version.
|
||||
*/
|
||||
queue = player_queue_get(0, 0);
|
||||
queue = player_queue_get_byindex(0, 0);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1912,12 +1914,12 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i].dbmfi_id, pos_pl);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i]);
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i].dbmfi_id);
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||
@ -1927,7 +1929,7 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
pos_pl++;
|
||||
}
|
||||
|
||||
queue_free(queue);
|
||||
queue_info_free(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2141,8 +2143,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct playlist_info *pli;
|
||||
struct player_source *ps;
|
||||
uint32_t pos;
|
||||
struct queue_item *items;
|
||||
int ret;
|
||||
|
||||
if (argc < 2)
|
||||
@ -2173,9 +2174,9 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
|
||||
//TODO If a second parameter is given only add the specified range of songs to the playqueue
|
||||
|
||||
ps = player_queue_make_pl(pli->id, &pos);
|
||||
items = queue_make_pl(pli->id);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
free_pli(pli, 0);
|
||||
|
||||
@ -2185,7 +2186,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
|
||||
ret = player_playback_start(NULL);
|
||||
if (ret < 0)
|
||||
@ -2422,7 +2423,7 @@ static int
|
||||
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
int ret;
|
||||
|
||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
||||
@ -2441,9 +2442,9 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
||||
|
||||
mpd_get_query_params_find(argc - 1, argv + 1, &qp);
|
||||
|
||||
ps = player_queue_make(&qp);
|
||||
items = queue_make(&qp);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||
if (ret < 0)
|
||||
@ -2451,7 +2452,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
|
||||
ret = player_playback_start(NULL);
|
||||
if (ret < 0)
|
||||
@ -2896,7 +2897,7 @@ static int
|
||||
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct player_source *ps;
|
||||
struct queue_item *items;
|
||||
int ret;
|
||||
|
||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
||||
@ -2915,9 +2916,9 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
|
||||
mpd_get_query_params_search(argc - 1, argv + 1, &qp);
|
||||
|
||||
ps = player_queue_make(&qp);
|
||||
items = queue_make(&qp);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||
if (ret < 0)
|
||||
@ -2925,7 +2926,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
player_queue_add(ps);
|
||||
player_queue_add(items);
|
||||
|
||||
ret = player_playback_start(NULL);
|
||||
if (ret < 0)
|
||||
|
1526
src/player.c
1526
src/player.c
File diff suppressed because it is too large
Load Diff
73
src/player.h
73
src/player.h
@ -5,6 +5,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "db.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* AirTunes v2 packet interval in ns */
|
||||
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
|
||||
@ -27,12 +28,6 @@ enum play_status {
|
||||
PLAY_PLAYING = 4,
|
||||
};
|
||||
|
||||
enum repeat_mode {
|
||||
REPEAT_OFF = 0,
|
||||
REPEAT_SONG = 1,
|
||||
REPEAT_ALL = 2,
|
||||
};
|
||||
|
||||
struct spk_flags {
|
||||
unsigned selected:1;
|
||||
unsigned has_password:1;
|
||||
@ -72,30 +67,6 @@ struct player_status {
|
||||
|
||||
typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg);
|
||||
|
||||
struct player_source
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t len_ms;
|
||||
|
||||
enum data_kind data_kind;
|
||||
enum media_kind media_kind;
|
||||
int setup_done;
|
||||
|
||||
uint64_t stream_start;
|
||||
uint64_t output_start;
|
||||
uint64_t end;
|
||||
|
||||
struct transcode_ctx *ctx;
|
||||
|
||||
struct player_source *pl_next;
|
||||
struct player_source *pl_prev;
|
||||
|
||||
struct player_source *shuffle_next;
|
||||
struct player_source *shuffle_prev;
|
||||
|
||||
struct player_source *play_next;
|
||||
};
|
||||
|
||||
struct player_queue
|
||||
{
|
||||
// The item id of the current playing item
|
||||
@ -146,10 +117,13 @@ int
|
||||
player_playback_start(uint32_t *idx_id);
|
||||
|
||||
int
|
||||
player_playback_startpos(int pos, uint32_t *itemid);
|
||||
player_playback_start_byindex(int pos, uint32_t *itemid);
|
||||
|
||||
int
|
||||
player_playback_startid(uint32_t id, uint32_t *itemid);
|
||||
player_playback_start_bypos(int pos, uint32_t *itemid);
|
||||
|
||||
int
|
||||
player_playback_start_byitemid(uint32_t id, uint32_t *itemid);
|
||||
|
||||
int
|
||||
player_playback_stop(void);
|
||||
@ -182,51 +156,38 @@ player_repeat_set(enum repeat_mode mode);
|
||||
int
|
||||
player_shuffle_set(int enable);
|
||||
|
||||
struct player_source *
|
||||
player_queue_make(struct query_params *qp);
|
||||
|
||||
//int
|
||||
//player_queue_make_daap(struct player_source **head, const char *query, const char *queuefilter, const char *sort, int quirk);
|
||||
struct queue_info *
|
||||
player_queue_get_bypos(int count);
|
||||
|
||||
struct player_source *
|
||||
player_queue_make_pl(int plid, uint32_t *id);
|
||||
|
||||
//struct player_source *
|
||||
//player_queue_make_mpd(char *path, int recursive);
|
||||
|
||||
struct player_queue *
|
||||
player_queue_get_relative(int count);
|
||||
|
||||
struct player_queue *
|
||||
player_queue_get(int pos, int count);
|
||||
|
||||
void
|
||||
queue_free(struct player_queue *queue);
|
||||
struct queue_info *
|
||||
player_queue_get_byindex(int pos, int count);
|
||||
|
||||
int
|
||||
player_queue_add(struct player_source *ps);
|
||||
player_queue_add(struct queue_item *items);
|
||||
|
||||
int
|
||||
player_queue_add_next(struct player_source *ps);
|
||||
player_queue_add_next(struct queue_item *items);
|
||||
|
||||
int
|
||||
player_queue_move(int ps_pos_from, int ps_pos_to);
|
||||
player_queue_move_bypos(int ps_pos_from, int ps_pos_to);
|
||||
|
||||
int
|
||||
player_queue_remove_pos_relative(int pos);
|
||||
player_queue_remove_bypos(int pos);
|
||||
|
||||
int
|
||||
player_queue_remove_queueitemid(uint32_t id);
|
||||
player_queue_remove_byitemid(uint32_t id);
|
||||
|
||||
void
|
||||
player_queue_clear(void);
|
||||
|
||||
void
|
||||
player_queue_empty(int clear_hist);
|
||||
player_queue_clear_history(void);
|
||||
|
||||
void
|
||||
player_queue_plid(uint32_t plid);
|
||||
|
||||
|
||||
struct player_history *
|
||||
player_history_get(void);
|
||||
|
||||
|
1091
src/queue.c
Normal file
1091
src/queue.c
Normal file
File diff suppressed because it is too large
Load Diff
129
src/queue.h
Normal file
129
src/queue.h
Normal file
@ -0,0 +1,129 @@
|
||||
|
||||
#ifndef SRC_QUEUE_H_
|
||||
#define SRC_QUEUE_H_
|
||||
|
||||
|
||||
enum repeat_mode {
|
||||
REPEAT_OFF = 0,
|
||||
REPEAT_SONG = 1,
|
||||
REPEAT_ALL = 2,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Internal representation of a queue
|
||||
*/
|
||||
struct queue;
|
||||
|
||||
/*
|
||||
* Internal representation of a list of queue items
|
||||
*/
|
||||
struct queue_item;
|
||||
|
||||
/*
|
||||
* External representation of an item in a queue
|
||||
*/
|
||||
struct queue_item_info
|
||||
{
|
||||
/* Item-Id is a unique id for this queue item. If the same item appears multiple
|
||||
times in the queue each corresponding queue item has its own id. */
|
||||
unsigned int item_id;
|
||||
|
||||
/* Id of the file/item in the files database */
|
||||
unsigned int dbmfi_id;
|
||||
|
||||
/* Length of the item in ms */
|
||||
unsigned int len_ms;
|
||||
|
||||
/* Data type of the item */
|
||||
enum data_kind data_kind;
|
||||
/* Media type of the item */
|
||||
enum media_kind media_kind;
|
||||
};
|
||||
|
||||
/*
|
||||
* External representation of a queue
|
||||
*/
|
||||
struct queue_info
|
||||
{
|
||||
// The number of items in the queue
|
||||
unsigned int length;
|
||||
|
||||
// The position (0-based) in the queue for the first item in the queue array
|
||||
unsigned int start_pos;
|
||||
// The number of items in the queue array
|
||||
unsigned int count;
|
||||
// The queue array (array of items infos)
|
||||
struct queue_item_info *queue;
|
||||
};
|
||||
|
||||
struct queue *
|
||||
queue_new();
|
||||
|
||||
void
|
||||
queue_free(struct queue *queue);
|
||||
|
||||
unsigned int
|
||||
queue_count(struct queue *queue);
|
||||
|
||||
int
|
||||
queueitem_pos(struct queue_item *item, uint32_t dbmfi_id);
|
||||
|
||||
struct queue_item_info *
|
||||
queue_get_byitemid(struct queue *queue, unsigned int item_id);
|
||||
|
||||
struct queue_item_info *
|
||||
queue_get_byindex(struct queue *queue, unsigned int index, char shuffle);
|
||||
|
||||
struct queue_item_info *
|
||||
queue_get_bypos(struct queue *queue, unsigned int item_id, unsigned int pos, char shuffle);
|
||||
|
||||
int
|
||||
queue_index_byitemid(struct queue *queue, unsigned int item_id, char shuffle);
|
||||
|
||||
struct queue_item_info *
|
||||
queue_next(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode);
|
||||
|
||||
struct queue_item_info *
|
||||
queue_prev(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode);
|
||||
|
||||
struct queue_info *
|
||||
queue_info_new_byindex(struct queue *queue, unsigned int index, unsigned int count, char shuffle);
|
||||
|
||||
struct queue_info *
|
||||
queue_info_new_bypos(struct queue *queue, unsigned int item_id, unsigned int count, char shuffle);
|
||||
|
||||
void
|
||||
queue_info_free(struct queue_info *qi);
|
||||
|
||||
void
|
||||
queue_add(struct queue *queue, struct queue_item *item);
|
||||
|
||||
void
|
||||
queue_add_after(struct queue *queue, struct queue_item *item, unsigned int item_id);
|
||||
|
||||
void
|
||||
queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_pos, unsigned int to_offset, char shuffle);
|
||||
|
||||
void
|
||||
queue_remove_byitemid(struct queue *queue, unsigned int item_id);
|
||||
|
||||
void
|
||||
queue_remove_byindex(struct queue *queue, unsigned int index, char shuffle);
|
||||
|
||||
void
|
||||
queue_remove_bypos(struct queue *queue, unsigned int item_id, unsigned int pos, char shuffle);
|
||||
|
||||
void
|
||||
queue_clear(struct queue *queue);
|
||||
|
||||
void
|
||||
queue_shuffle(struct queue *queue, unsigned int item_id);
|
||||
|
||||
struct queue_item *
|
||||
queue_make(struct query_params *qp);
|
||||
|
||||
struct queue_item *
|
||||
queue_make_pl(int plid);
|
||||
|
||||
#endif /* SRC_QUEUE_H_ */
|
Loading…
Reference in New Issue
Block a user