mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-28 15:06:02 -05:00
Merge pull request #183 from chme/queuerefactor3
Queue/player refactoring
This commit is contained in:
commit
34cc45b12d
@ -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 \
|
||||
|
2
src/db.h
2
src/db.h
@ -157,7 +157,7 @@ struct media_file_info {
|
||||
|
||||
uint32_t item_kind; /* song or movie */
|
||||
uint32_t data_kind; /* dmap.datakind (asdk) */
|
||||
uint64_t sample_count;
|
||||
uint64_t sample_count; //TODO [unused] sample count is never set and therefor always 0
|
||||
uint32_t compilation;
|
||||
char artwork;
|
||||
|
||||
|
274
src/httpd_dacp.c
274
src/httpd_dacp.c
@ -48,7 +48,9 @@
|
||||
#include "httpd_dacp.h"
|
||||
#include "dmap_common.h"
|
||||
#include "db.h"
|
||||
#include "daap_query.h"
|
||||
#include "player.h"
|
||||
#include "queue.h"
|
||||
#include "listener.h"
|
||||
|
||||
/* httpd event base, from httpd.c */
|
||||
@ -753,15 +755,219 @@ dacp_reply_ctrlint(struct evhttp_request *req, struct evbuffer *evbuf, char **ur
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
}
|
||||
|
||||
static int
|
||||
find_first_song_id(const char *query)
|
||||
{
|
||||
struct db_media_file_info dbmfi;
|
||||
struct query_params qp;
|
||||
int id;
|
||||
int ret;
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
/* We only want the id of the first song */
|
||||
qp.type = Q_ITEMS;
|
||||
qp.idx_type = I_FIRST;
|
||||
qp.sort = S_NONE;
|
||||
qp.offset = 0;
|
||||
qp.limit = 1;
|
||||
qp.filter = daap_query_parse_sql(query);
|
||||
if (!qp.filter)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Improper DAAP query!\n");
|
||||
|
||||
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_atoi32(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 (id %d)\n", id);
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "No song matches query (results %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 id;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dacp_queueitem_make(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 queue_item *items;
|
||||
int64_t albumid;
|
||||
int64_t artistid;
|
||||
int plid;
|
||||
int id;
|
||||
int idx;
|
||||
int ret;
|
||||
int len;
|
||||
char *s;
|
||||
char buf[1024];
|
||||
|
||||
if (query)
|
||||
{
|
||||
id = find_first_song_id(query);
|
||||
if (id < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
id = 0;
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
qp.offset = 0;
|
||||
qp.limit = 0;
|
||||
qp.sort = S_NONE;
|
||||
qp.idx_type = I_NONE;
|
||||
|
||||
if (quirk)
|
||||
{
|
||||
qp.sort = S_ALBUM;
|
||||
qp.type = Q_ITEMS;
|
||||
mfi = db_file_fetch_byid(id);
|
||||
if (!mfi)
|
||||
return -1;
|
||||
snprintf(buf, sizeof(buf), "f.songalbumid = %" PRIi64, mfi->songalbumid);
|
||||
free_mfi(mfi, 0);
|
||||
qp.filter = strdup(buf);
|
||||
}
|
||||
else if (queuefilter)
|
||||
{
|
||||
len = strlen(queuefilter);
|
||||
if ((len > 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 ((len > 7) && (strncmp(queuefilter, "artist:", 7) == 0))
|
||||
{
|
||||
qp.type = Q_ITEMS;
|
||||
ret = safe_atoi64(strchr(queuefilter, ':') + 1, &artistid);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Invalid artist id in queuefilter: %s\n", queuefilter);
|
||||
|
||||
return -1;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "f.songartistid = %" PRIi64, artistid);
|
||||
qp.filter = strdup(buf);
|
||||
}
|
||||
else if ((len > 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 if ((len > 6) && (strncmp(queuefilter, "genre:", 6) == 0))
|
||||
{
|
||||
qp.type = Q_ITEMS;
|
||||
s = db_escape_string(queuefilter + 6);
|
||||
if (!s)
|
||||
return -1;
|
||||
snprintf(buf, sizeof(buf), "f.genre = '%s'", s);
|
||||
qp.filter = strdup(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Unknown queuefilter %s\n", queuefilter);
|
||||
|
||||
// If the queuefilter is unkown, ignore it and use the query parameter instead to build the sql query
|
||||
id = 0;
|
||||
qp.type = Q_ITEMS;
|
||||
qp.filter = daap_query_parse_sql(query);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = 0;
|
||||
qp.type = Q_ITEMS;
|
||||
qp.filter = daap_query_parse_sql(query);
|
||||
}
|
||||
|
||||
if (sort)
|
||||
{
|
||||
if (strcmp(sort, "name") == 0)
|
||||
qp.sort = S_NAME;
|
||||
else if (strcmp(sort, "album") == 0)
|
||||
qp.sort = S_ALBUM;
|
||||
else if (strcmp(sort, "artist") == 0)
|
||||
qp.sort = S_ARTIST;
|
||||
}
|
||||
|
||||
items = queueitem_make_byquery(&qp);
|
||||
|
||||
if (qp.filter)
|
||||
free(qp.filter);
|
||||
|
||||
if (items)
|
||||
*head = items;
|
||||
else
|
||||
return -1;
|
||||
|
||||
// Get the position (0-based) of the first item
|
||||
idx = queueitem_pos(items, id);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t id;
|
||||
uint32_t item_id;
|
||||
uint32_t pos;
|
||||
int clear;
|
||||
struct player_history *history;
|
||||
@ -789,7 +995,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
sort = evhttp_find_header(query, "sort");
|
||||
|
||||
ret = player_queue_make_daap(&ps, cuequery, NULL, sort, 0);
|
||||
ret = dacp_queueitem_make(&items, cuequery, NULL, sort, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
||||
@ -798,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
|
||||
{
|
||||
@ -813,6 +1019,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
dacp_propset_shufflestate(param, NULL);
|
||||
|
||||
id = 0;
|
||||
item_id = 0;
|
||||
pos = 0;
|
||||
param = evhttp_find_header(query, "index");
|
||||
if (param)
|
||||
@ -836,7 +1043,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
if (history->count > pos)
|
||||
{
|
||||
pos = (history->start_index + history->count - pos - 1) % MAX_HISTORY_COUNT;
|
||||
id = history->id[pos];
|
||||
item_id = history->item_id[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -855,9 +1062,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(item_id, &id);
|
||||
else
|
||||
ret = player_playback_startpos(pos, &id);
|
||||
ret = player_playback_start_bypos(pos, &id);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -926,7 +1133,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;
|
||||
@ -1008,8 +1215,13 @@ 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 = NULL;
|
||||
if (plid > 0)
|
||||
items = queueitem_make_byplid(plid);
|
||||
else if (pos > 0)
|
||||
items = queueitem_make_byid(pos);
|
||||
|
||||
if (!items)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue from playlist %d\n", plid);
|
||||
|
||||
@ -1024,13 +1236,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");
|
||||
@ -1264,11 +1476,13 @@ 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 *queue;
|
||||
struct queue_item *item;
|
||||
const char *param;
|
||||
size_t songlist_length;
|
||||
size_t playlist_length;
|
||||
int span;
|
||||
int count;
|
||||
int i;
|
||||
int n;
|
||||
int ret;
|
||||
@ -1336,13 +1550,15 @@ 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(-1, abs(span), status.shuffle);
|
||||
queue = player_queue_get_bypos(abs(span));
|
||||
if (queue)
|
||||
{
|
||||
i = queue->start_pos;
|
||||
for (n = 0; (n < queue->count) && (n < abs(span)); n++)
|
||||
i = 0;
|
||||
count = queue_count(queue);
|
||||
for (n = 0; (n < count) && (n < abs(span)); n++)
|
||||
{
|
||||
ret = playqueuecontents_add_source(songlist, queue->queue[n], (n + i + 1), status.plid);
|
||||
item = queue_get_byindex(queue, n, 0);
|
||||
ret = playqueuecontents_add_source(songlist, queueitem_id(item), (n + i + 1), status.plid);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n");
|
||||
@ -1351,8 +1567,8 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
return;
|
||||
}
|
||||
}
|
||||
queue_free(queue);
|
||||
}
|
||||
queue_free(queue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1436,9 +1652,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");
|
||||
|
||||
/*
|
||||
@ -1447,9 +1661,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 */
|
||||
@ -1470,7 +1684,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;
|
||||
@ -1522,7 +1736,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 = player_queue_make_daap(&ps, editquery, queuefilter, sort, quirkyquery);
|
||||
ret = dacp_queueitem_make(&items, editquery, queuefilter, sort, quirkyquery);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1537,7 +1751,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
}
|
||||
|
||||
snprintf(modifiedquery, sizeof(modifiedquery), "playlist:%d", plid);
|
||||
ret = player_queue_make_daap(&ps, NULL, modifiedquery, sort, 0);
|
||||
ret = dacp_queueitem_make(&items, NULL, modifiedquery, sort, 0);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
@ -1552,11 +1766,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
|
||||
@ -1574,7 +1788,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");
|
||||
@ -1625,7 +1839,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 */
|
||||
@ -1657,7 +1871,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb
|
||||
return;
|
||||
}
|
||||
|
||||
player_queue_remove(item_index);
|
||||
player_queue_remove_bypos(item_index);
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
|
161
src/mpd.c
161
src/mpd.c
@ -57,6 +57,7 @@
|
||||
#include "artwork.h"
|
||||
|
||||
#include "player.h"
|
||||
#include "queue.h"
|
||||
#include "filescanner.h"
|
||||
|
||||
|
||||
@ -470,11 +471,12 @@ mpd_parse_args(char *args, int *argc, char **argv)
|
||||
*
|
||||
* @param evbuf the response event buffer
|
||||
* @param mfi media information
|
||||
* @param item_id queue-item id
|
||||
* @param pos_pl position in the playqueue, if -1 the position is ignored
|
||||
* @return the number of bytes added if successful, or -1 if an error occurred.
|
||||
*/
|
||||
static int
|
||||
mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, int pos_pl)
|
||||
mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, unsigned int item_id, int pos_pl)
|
||||
{
|
||||
char modified[32];
|
||||
int ret;
|
||||
@ -515,10 +517,9 @@ mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, int pos_p
|
||||
"Pos: %d\n",
|
||||
pos_pl);
|
||||
|
||||
//TODO mpd does not return the persistent id of a file but instead a unique id in the current playlist
|
||||
ret = evbuffer_add_printf(evbuf,
|
||||
"Id: %d\n",
|
||||
mfi->id);
|
||||
item_id);
|
||||
}
|
||||
|
||||
|
||||
@ -526,7 +527,7 @@ mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, int pos_p
|
||||
}
|
||||
|
||||
static int
|
||||
mpd_add_mediainfo_byid(struct evbuffer *evbuf, int id, int pos_pl)
|
||||
mpd_add_mediainfo_byid(struct evbuffer *evbuf, int id, unsigned int item_id, int pos_pl)
|
||||
{
|
||||
struct media_file_info *mfi;
|
||||
int ret;
|
||||
@ -538,7 +539,7 @@ mpd_add_mediainfo_byid(struct evbuffer *evbuf, int id, int pos_pl)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mpd_add_mediainfo(evbuf, mfi, pos_pl);
|
||||
ret = mpd_add_mediainfo(evbuf, mfi, item_id, pos_pl);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Error adding media info for file with id: %d\n", id);
|
||||
@ -649,7 +650,7 @@ mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **er
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = mpd_add_mediainfo_byid(evbuf, status.id, status.pos_pl);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, status.id, status.item_id, status.pos_pl);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", status.id);
|
||||
@ -838,11 +839,11 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
"nextsong: %d\n"
|
||||
"nextsongid: %d\n",
|
||||
status.pos_pl,
|
||||
status.id,
|
||||
status.item_id,
|
||||
(status.pos_ms / 1000), (status.len_ms / 1000),
|
||||
(status.pos_ms / 1000.0),
|
||||
status.next_pos_pl,
|
||||
status.next_id);
|
||||
status.next_item_id);
|
||||
}
|
||||
|
||||
if (filescanner_scanning())
|
||||
@ -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,6 +1507,37 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct queue_item *
|
||||
mpd_queueitem_make(char *path, int recursive)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct queue_item *items;
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
qp.type = Q_ITEMS;
|
||||
qp.idx_type = I_NONE;
|
||||
qp.sort = S_ALBUM;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
qp.filter = sqlite3_mprintf("f.virtual_path LIKE '/%q%%'", path);
|
||||
if (!qp.filter)
|
||||
DPRINTF(E_DBG, L_PLAYER, "Out of memory\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
qp.filter = sqlite3_mprintf("f.virtual_path LIKE '/%q'", path);
|
||||
if (!qp.filter)
|
||||
DPRINTF(E_DBG, L_PLAYER, "Out of memory\n");
|
||||
}
|
||||
|
||||
items = queueitem_make_byquery(&qp);
|
||||
|
||||
sqlite3_free(qp.filter);
|
||||
return items;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command handler function for 'add'
|
||||
* Adds the all songs under the given path to the end of the playqueue (directories add recursively).
|
||||
@ -1514,7 +1546,7 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
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)
|
||||
@ -1525,9 +1557,9 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ps = player_queue_make_mpd(argv[1], 1);
|
||||
items = mpd_queueitem_make(argv[1], 1);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||
if (ret < 0)
|
||||
@ -1535,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)
|
||||
@ -1555,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)
|
||||
@ -1572,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 = player_queue_make_mpd(argv[1], 0);
|
||||
items = mpd_queueitem_make(argv[1], 0);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||
if (ret < 0)
|
||||
@ -1583,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)
|
||||
@ -1637,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;
|
||||
}
|
||||
|
||||
@ -1664,7 +1697,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ret = player_queue_remove(pos);
|
||||
ret = player_queue_remove_bypos(pos);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to remove song at position '%d'", pos);
|
||||
@ -1703,7 +1736,7 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ret = player_queue_removeid(songid);
|
||||
ret = player_queue_remove_byitemid(songid);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to remove song with id '%s'", argv[1]);
|
||||
@ -1725,9 +1758,11 @@ 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 *queue;
|
||||
struct queue_item *item;
|
||||
uint32_t songid;
|
||||
int pos_pl;
|
||||
int count;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
@ -1746,7 +1781,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, -1, 0);
|
||||
queue = player_queue_get_byindex(0, 0);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1754,15 +1789,17 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
pos_pl = 0;
|
||||
count = queue_count(queue);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (songid == 0 || songid == queue->queue[i])
|
||||
item = queue_get_byindex(queue, i, 0);
|
||||
if (songid == 0 || songid == queueitem_item_id(item))
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), 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", queueitem_id(item));
|
||||
|
||||
queue_free(queue);
|
||||
|
||||
@ -1791,15 +1828,17 @@ 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 *queue;
|
||||
struct queue_item *item;
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
int count;
|
||||
int pos_pl;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
start_pos = 0;
|
||||
end_pos = -1;
|
||||
end_pos = 0;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
@ -1813,13 +1852,16 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
}
|
||||
}
|
||||
|
||||
count = end_pos - start_pos;
|
||||
|
||||
if (start_pos < 0)
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Command 'playlistinfo' called with pos < 0 (arg = '%s'), ignore arguments and return whole queue\n", argv[1]);
|
||||
start_pos = 0;
|
||||
end_pos = -1;
|
||||
count = 0;
|
||||
}
|
||||
queue = player_queue_get(start_pos, end_pos, 0);
|
||||
|
||||
queue = player_queue_get_byindex(start_pos, count);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1827,13 +1869,15 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
pos_pl = start_pos;
|
||||
count = queue_count(queue);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
item = queue_get_byindex(queue, i, 0);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), 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", queueitem_id(item));
|
||||
|
||||
queue_free(queue);
|
||||
|
||||
@ -1857,8 +1901,10 @@ 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 *queue;
|
||||
struct queue_item *item;
|
||||
int pos_pl;
|
||||
int count;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
@ -1866,7 +1912,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, -1, 0);
|
||||
queue = player_queue_get_byindex(0, 0);
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
@ -1874,13 +1920,15 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos_pl = queue->start_pos;
|
||||
for (i = 0; i < queue->count; i++)
|
||||
pos_pl = 0;
|
||||
count = queue_count(queue);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl);
|
||||
item = queue_get_byindex(queue, i, 0);
|
||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), 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", queueitem_id(item));
|
||||
|
||||
queue_free(queue);
|
||||
|
||||
@ -2106,8 +2154,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)
|
||||
@ -2138,9 +2185,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 = queueitem_make_byplid(pli->id);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
free_pli(pli, 0);
|
||||
|
||||
@ -2150,7 +2197,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)
|
||||
@ -2387,7 +2434,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)
|
||||
@ -2406,9 +2453,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 = queueitem_make_byquery(&qp);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||
if (ret < 0)
|
||||
@ -2416,7 +2463,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)
|
||||
@ -2655,7 +2702,7 @@ mpd_command_lsinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mfi = db_file_fetch_byvirtualpath(fi->virtual_path);
|
||||
if (mfi)
|
||||
{
|
||||
ret = mpd_add_mediainfo(evbuf, mfi, -1);
|
||||
ret = mpd_add_mediainfo(evbuf, mfi, 0, -1);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Could not add mediainfo for path '%s'\n", fi->virtual_path);
|
||||
@ -2861,7 +2908,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)
|
||||
@ -2880,9 +2927,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 = queueitem_make_byquery(&qp);
|
||||
|
||||
if (!ps)
|
||||
if (!items)
|
||||
{
|
||||
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||
if (ret < 0)
|
||||
@ -2890,7 +2937,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)
|
||||
|
2813
src/player.c
2813
src/player.c
File diff suppressed because it is too large
Load Diff
98
src/player.h
98
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;
|
||||
@ -56,8 +51,10 @@ struct player_status {
|
||||
uint32_t plversion;
|
||||
/* Playlist length */
|
||||
uint32_t playlistlength;
|
||||
/* Playing song id*/
|
||||
/* Id of the playing file/item in the files database */
|
||||
uint32_t id;
|
||||
/* Item-Id of the playing file/item in the queue */
|
||||
uint32_t item_id;
|
||||
/* Elapsed time in ms of playing item */
|
||||
uint32_t pos_ms;
|
||||
/* Length in ms of playing item */
|
||||
@ -66,51 +63,14 @@ struct player_status {
|
||||
int pos_pl;
|
||||
/* Item id of next item in playlist */
|
||||
uint32_t next_id;
|
||||
/* Item-Id of the next file/item in the queue */
|
||||
uint32_t next_item_id;
|
||||
/* Playlist position of next item */
|
||||
int next_pos_pl;
|
||||
};
|
||||
|
||||
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
|
||||
uint32_t playingid;
|
||||
// The number of items in the queue
|
||||
unsigned int length;
|
||||
|
||||
// The position 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 item ids)
|
||||
uint32_t *queue;
|
||||
};
|
||||
|
||||
struct player_history
|
||||
{
|
||||
/* Buffer index of the oldest remembered song */
|
||||
@ -121,6 +81,7 @@ struct player_history
|
||||
|
||||
/* Circular buffer of song ids previously played by forked-daapd */
|
||||
uint32_t id[MAX_HISTORY_COUNT];
|
||||
uint32_t item_id[MAX_HISTORY_COUNT];
|
||||
};
|
||||
|
||||
|
||||
@ -143,13 +104,16 @@ int
|
||||
player_speaker_set(uint64_t *ids);
|
||||
|
||||
int
|
||||
player_playback_start(uint32_t *idx_id);
|
||||
player_playback_start(uint32_t *id);
|
||||
|
||||
int
|
||||
player_playback_startpos(int pos, uint32_t *itemid);
|
||||
player_playback_start_byindex(int pos, uint32_t *id);
|
||||
|
||||
int
|
||||
player_playback_startid(uint32_t id, uint32_t *itemid);
|
||||
player_playback_start_bypos(int pos, uint32_t *id);
|
||||
|
||||
int
|
||||
player_playback_start_byitemid(uint32_t item_id, uint32_t *id);
|
||||
|
||||
int
|
||||
player_playback_stop(void);
|
||||
@ -182,48 +146,38 @@ player_repeat_set(enum repeat_mode mode);
|
||||
int
|
||||
player_shuffle_set(int enable);
|
||||
|
||||
struct player_source *
|
||||
player_queue_make(struct query_params *qp);
|
||||
|
||||
struct queue *
|
||||
player_queue_get_bypos(int count);
|
||||
|
||||
struct queue *
|
||||
player_queue_get_byindex(int pos, int count);
|
||||
|
||||
int
|
||||
player_queue_make_daap(struct player_source **head, const char *query, const char *queuefilter, const char *sort, int quirk);
|
||||
|
||||
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(int start_pos, int end_pos, char shuffle);
|
||||
|
||||
void
|
||||
queue_free(struct player_queue *queue);
|
||||
player_queue_add(struct queue_item *items);
|
||||
|
||||
int
|
||||
player_queue_add(struct player_source *ps);
|
||||
player_queue_add_next(struct queue_item *items);
|
||||
|
||||
int
|
||||
player_queue_add_next(struct player_source *ps);
|
||||
player_queue_move_bypos(int ps_pos_from, int ps_pos_to);
|
||||
|
||||
int
|
||||
player_queue_move(int ps_pos_from, int ps_pos_to);
|
||||
player_queue_remove_bypos(int pos);
|
||||
|
||||
int
|
||||
player_queue_remove(int ps_pos_remove);
|
||||
|
||||
int
|
||||
player_queue_removeid(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);
|
||||
|
||||
|
1176
src/queue.c
Normal file
1176
src/queue.c
Normal file
File diff suppressed because it is too large
Load Diff
110
src/queue.h
Normal file
110
src/queue.h
Normal file
@ -0,0 +1,110 @@
|
||||
|
||||
#ifndef SRC_QUEUE_H_
|
||||
#define SRC_QUEUE_H_
|
||||
|
||||
|
||||
#include "db.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;
|
||||
|
||||
|
||||
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 id);
|
||||
|
||||
uint32_t
|
||||
queueitem_id(struct queue_item *item);
|
||||
|
||||
unsigned int
|
||||
queueitem_item_id(struct queue_item *item);
|
||||
|
||||
unsigned int
|
||||
queueitem_len(struct queue_item *item);
|
||||
|
||||
enum data_kind
|
||||
queueitem_data_kind(struct queue_item *item);
|
||||
|
||||
enum media_kind
|
||||
queueitem_media_kind(struct queue_item *item);
|
||||
|
||||
struct queue_item *
|
||||
queue_get_byitemid(struct queue *queue, unsigned int item_id);
|
||||
|
||||
struct queue_item *
|
||||
queue_get_byindex(struct queue *queue, unsigned int index, char shuffle);
|
||||
|
||||
struct queue_item *
|
||||
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 *
|
||||
queue_next(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode, int reshuffle);
|
||||
|
||||
struct queue_item *
|
||||
queue_prev(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode);
|
||||
|
||||
struct queue *
|
||||
queue_new_byindex(struct queue *queue, unsigned int index, unsigned int count, char shuffle);
|
||||
|
||||
struct queue *
|
||||
queue_new_bypos(struct queue *queue, unsigned int item_id, unsigned int count, char shuffle);
|
||||
|
||||
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 *
|
||||
queueitem_make_byquery(struct query_params *qp);
|
||||
|
||||
struct queue_item *
|
||||
queueitem_make_byplid(int plid);
|
||||
|
||||
struct queue_item *
|
||||
queueitem_make_byid(uint32_t id);
|
||||
|
||||
#endif /* SRC_QUEUE_H_ */
|
102
src/spotify.c
102
src/spotify.c
@ -912,12 +912,12 @@ audio_fifo_flush(void)
|
||||
}
|
||||
|
||||
static int
|
||||
playback_play(struct spotify_command *cmd)
|
||||
playback_setup(struct spotify_command *cmd)
|
||||
{
|
||||
sp_track *track;
|
||||
sp_error err;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Starting playback\n");
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Setting up for playback\n");
|
||||
|
||||
if (SP_CONNECTION_STATE_LOGGED_IN != fptr_sp_session_connectionstate(g_sess))
|
||||
{
|
||||
@ -947,6 +947,16 @@ playback_play(struct spotify_command *cmd)
|
||||
|
||||
audio_fifo_flush();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
playback_play(struct spotify_command *cmd)
|
||||
{
|
||||
sp_error err;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Starting playback\n");
|
||||
|
||||
err = fptr_sp_session_player_play(g_sess, 1);
|
||||
if (SP_ERROR_OK != err)
|
||||
{
|
||||
@ -980,25 +990,6 @@ playback_pause(struct spotify_command *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
playback_resume(struct spotify_command *cmd)
|
||||
{
|
||||
sp_error err;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Resuming playback\n");
|
||||
|
||||
err = fptr_sp_session_player_play(g_sess, 1);
|
||||
if (SP_ERROR_OK != err)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Playback resume failed: %s\n", fptr_sp_error_message(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_state = SPOTIFY_STATE_PLAYING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
playback_stop(struct spotify_command *cmd)
|
||||
{
|
||||
@ -1071,7 +1062,7 @@ audio_get(struct spotify_command *cmd)
|
||||
|
||||
// If spotify was paused begin by resuming playback
|
||||
if (g_state == SPOTIFY_STATE_PAUSED)
|
||||
playback_resume(NULL);
|
||||
playback_play(NULL);
|
||||
|
||||
pthread_mutex_lock(&g_audio_fifo->mutex);
|
||||
|
||||
@ -1626,13 +1617,13 @@ notify_cb(int fd, short what, void *arg)
|
||||
|
||||
/* Thread: player */
|
||||
int
|
||||
spotify_playback_play(struct media_file_info *mfi)
|
||||
spotify_playback_setup(struct media_file_info *mfi)
|
||||
{
|
||||
struct spotify_command cmd;
|
||||
sp_link *link;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Playback request\n");
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Playback setup request\n");
|
||||
|
||||
link = fptr_sp_link_create_from_string(mfi->path);
|
||||
if (!link)
|
||||
@ -1643,7 +1634,7 @@ spotify_playback_play(struct media_file_info *mfi)
|
||||
|
||||
command_init(&cmd);
|
||||
|
||||
cmd.func = playback_play;
|
||||
cmd.func = playback_setup;
|
||||
cmd.arg.link = link;
|
||||
|
||||
ret = sync_command(&cmd);
|
||||
@ -1653,6 +1644,46 @@ spotify_playback_play(struct media_file_info *mfi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
spotify_playback_play()
|
||||
{
|
||||
struct spotify_command cmd;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Playback request\n");
|
||||
|
||||
command_init(&cmd);
|
||||
|
||||
cmd.func = playback_play;
|
||||
cmd.arg.noarg = NULL;
|
||||
|
||||
ret = sync_command(&cmd);
|
||||
|
||||
command_deinit(&cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
spotify_playback_pause()
|
||||
{
|
||||
struct spotify_command cmd;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Pause request\n");
|
||||
|
||||
command_init(&cmd);
|
||||
|
||||
cmd.func = playback_pause;
|
||||
cmd.arg.noarg = NULL;
|
||||
|
||||
ret = sync_command(&cmd);
|
||||
|
||||
command_deinit(&cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Thread: libspotify */
|
||||
void
|
||||
spotify_playback_pause_nonblock(void)
|
||||
@ -1678,27 +1709,6 @@ spotify_playback_pause_nonblock(void)
|
||||
nonblock_command(cmd);
|
||||
}
|
||||
|
||||
/* Not used */
|
||||
int
|
||||
spotify_playback_resume(void)
|
||||
{
|
||||
struct spotify_command cmd;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Resume request\n");
|
||||
|
||||
command_init(&cmd);
|
||||
|
||||
cmd.func = playback_resume;
|
||||
cmd.arg.noarg = NULL;
|
||||
|
||||
ret = sync_command(&cmd);
|
||||
|
||||
command_deinit(&cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Thread: player and libspotify */
|
||||
int
|
||||
spotify_playback_stop(void)
|
||||
|
@ -11,7 +11,13 @@
|
||||
#endif
|
||||
|
||||
int
|
||||
spotify_playback_play(struct media_file_info *mfi);
|
||||
spotify_playback_setup(struct media_file_info *mfi);
|
||||
|
||||
int
|
||||
spotify_playback_play();
|
||||
|
||||
int
|
||||
spotify_playback_pause();
|
||||
|
||||
void
|
||||
spotify_playback_pause_nonblock(void);
|
||||
|
@ -731,7 +731,7 @@ transcode_setup(struct transcode_ctx **nctx, struct media_file_info *mfi, off_t
|
||||
}
|
||||
|
||||
ctx->duration = mfi->song_length;
|
||||
ctx->samples = mfi->sample_count;
|
||||
ctx->samples = mfi->sample_count; //TODO [unused] sample count is never set and therefor always 0
|
||||
ctx->wavhdr = wavhdr;
|
||||
|
||||
if (wavhdr)
|
||||
|
Loading…
x
Reference in New Issue
Block a user