mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-27 13:54:49 -04: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 \
|
rsp_query.c rsp_query.h \
|
||||||
daap_query.c daap_query.h \
|
daap_query.c daap_query.h \
|
||||||
player.c player.h \
|
player.c player.h \
|
||||||
|
queue.c queue.h \
|
||||||
worker.c worker.h \
|
worker.c worker.h \
|
||||||
$(ALSA_SRC) $(OSS4_SRC) \
|
$(ALSA_SRC) $(OSS4_SRC) \
|
||||||
laudio_dummy.c \
|
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 item_kind; /* song or movie */
|
||||||
uint32_t data_kind; /* dmap.datakind (asdk) */
|
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;
|
uint32_t compilation;
|
||||||
char artwork;
|
char artwork;
|
||||||
|
|
||||||
|
274
src/httpd_dacp.c
274
src/httpd_dacp.c
@ -48,7 +48,9 @@
|
|||||||
#include "httpd_dacp.h"
|
#include "httpd_dacp.h"
|
||||||
#include "dmap_common.h"
|
#include "dmap_common.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
#include "daap_query.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "queue.h"
|
||||||
#include "listener.h"
|
#include "listener.h"
|
||||||
|
|
||||||
/* httpd event base, from httpd.c */
|
/* 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);
|
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
|
static void
|
||||||
dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
const char *sort;
|
const char *sort;
|
||||||
const char *cuequery;
|
const char *cuequery;
|
||||||
const char *param;
|
const char *param;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
uint32_t item_id;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
int clear;
|
int clear;
|
||||||
struct player_history *history;
|
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");
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -813,6 +1019,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
|||||||
dacp_propset_shufflestate(param, NULL);
|
dacp_propset_shufflestate(param, NULL);
|
||||||
|
|
||||||
id = 0;
|
id = 0;
|
||||||
|
item_id = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
param = evhttp_find_header(query, "index");
|
param = evhttp_find_header(query, "index");
|
||||||
if (param)
|
if (param)
|
||||||
@ -836,7 +1043,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
|||||||
if (history->count > pos)
|
if (history->count > pos)
|
||||||
{
|
{
|
||||||
pos = (history->start_index + history->count - pos - 1) % MAX_HISTORY_COUNT;
|
pos = (history->start_index + history->count - pos - 1) % MAX_HISTORY_COUNT;
|
||||||
id = history->id[pos];
|
item_id = history->item_id[pos];
|
||||||
}
|
}
|
||||||
else
|
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 playing from history queue, the pos holds the id of the item to play */
|
||||||
if (hist)
|
if (hist)
|
||||||
ret = player_playback_startid(id, &id);
|
ret = player_playback_start_byitemid(item_id, &id);
|
||||||
else
|
else
|
||||||
ret = player_playback_startpos(pos, &id);
|
ret = player_playback_start_bypos(pos, &id);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -926,7 +1133,7 @@ static void
|
|||||||
dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
struct daap_session *s;
|
struct daap_session *s;
|
||||||
const char *param;
|
const char *param;
|
||||||
const char *shuffle;
|
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" : "");
|
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);
|
items = NULL;
|
||||||
if (!ps)
|
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);
|
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_playback_stop();
|
||||||
|
|
||||||
player_queue_clear();
|
player_queue_clear();
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
player_queue_plid(plid);
|
player_queue_plid(plid);
|
||||||
|
|
||||||
if (shuffle)
|
if (shuffle)
|
||||||
dacp_propset_shufflestate(shuffle, NULL);
|
dacp_propset_shufflestate(shuffle, NULL);
|
||||||
|
|
||||||
ret = player_playback_startpos(pos, &id);
|
ret = player_playback_start_bypos(pos, &id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
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 evbuffer *playlists;
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
struct player_history *history;
|
struct player_history *history;
|
||||||
struct player_queue *queue;
|
struct queue *queue;
|
||||||
|
struct queue_item *item;
|
||||||
const char *param;
|
const char *param;
|
||||||
size_t songlist_length;
|
size_t songlist_length;
|
||||||
size_t playlist_length;
|
size_t playlist_length;
|
||||||
int span;
|
int span;
|
||||||
|
int count;
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
int ret;
|
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 */
|
/* Get queue and make songlist only if playing or paused */
|
||||||
if (status.status != PLAY_STOPPED)
|
if (status.status != PLAY_STOPPED)
|
||||||
{
|
{
|
||||||
queue = player_queue_get(-1, abs(span), status.shuffle);
|
queue = player_queue_get_bypos(abs(span));
|
||||||
if (queue)
|
if (queue)
|
||||||
{
|
{
|
||||||
i = queue->start_pos;
|
i = 0;
|
||||||
for (n = 0; (n < queue->count) && (n < abs(span)); n++)
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n");
|
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;
|
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)
|
dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
const char *param;
|
const char *param;
|
||||||
int clear_hist;
|
|
||||||
|
|
||||||
clear_hist = 0;
|
|
||||||
param = evhttp_find_header(query, "mode");
|
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.
|
* otherwise the current playlist.
|
||||||
*/
|
*/
|
||||||
if (strcmp(param,"0x68697374") == 0)
|
if (strcmp(param,"0x68697374") == 0)
|
||||||
clear_hist = 1;
|
player_queue_clear_history();
|
||||||
|
else
|
||||||
player_queue_empty(clear_hist);
|
player_queue_clear();
|
||||||
|
|
||||||
dmap_add_container(evbuf, "cacr", 24); /* 8 + len */
|
dmap_add_container(evbuf, "cacr", 24); /* 8 + len */
|
||||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
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
|
//?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
|
// -> 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 *editquery;
|
||||||
const char *queuefilter;
|
const char *queuefilter;
|
||||||
const char *querymodifier;
|
const char *querymodifier;
|
||||||
@ -1522,7 +1736,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
if (!querymodifier || (strcmp(querymodifier, "containers") != 0))
|
if (!querymodifier || (strcmp(querymodifier, "containers") != 0))
|
||||||
{
|
{
|
||||||
quirkyquery = (mode == 1) && strstr(editquery, "dmap.itemid:") && ((!queuefilter) || strstr(queuefilter, "(null)"));
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -1537,7 +1751,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
snprintf(modifiedquery, sizeof(modifiedquery), "playlist:%d", plid);
|
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)
|
if (ret < 0)
|
||||||
@ -1552,11 +1766,11 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
|
|
||||||
if (mode == 3)
|
if (mode == 3)
|
||||||
{
|
{
|
||||||
player_queue_add_next(ps);
|
player_queue_add_next(items);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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);
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_move(src, dst);
|
player_queue_move_bypos(src, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 204 No Content is the canonical reply */
|
||||||
@ -1657,7 +1871,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_remove(item_index);
|
player_queue_remove_bypos(item_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 204 No Content is the canonical reply */
|
||||||
|
161
src/mpd.c
161
src/mpd.c
@ -57,6 +57,7 @@
|
|||||||
#include "artwork.h"
|
#include "artwork.h"
|
||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "queue.h"
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
|
|
||||||
|
|
||||||
@ -470,11 +471,12 @@ mpd_parse_args(char *args, int *argc, char **argv)
|
|||||||
*
|
*
|
||||||
* @param evbuf the response event buffer
|
* @param evbuf the response event buffer
|
||||||
* @param mfi media information
|
* @param mfi media information
|
||||||
|
* @param item_id queue-item id
|
||||||
* @param pos_pl position in the playqueue, if -1 the position is ignored
|
* @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.
|
* @return the number of bytes added if successful, or -1 if an error occurred.
|
||||||
*/
|
*/
|
||||||
static int
|
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];
|
char modified[32];
|
||||||
int ret;
|
int ret;
|
||||||
@ -515,10 +517,9 @@ mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, int pos_p
|
|||||||
"Pos: %d\n",
|
"Pos: %d\n",
|
||||||
pos_pl);
|
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,
|
ret = evbuffer_add_printf(evbuf,
|
||||||
"Id: %d\n",
|
"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
|
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;
|
struct media_file_info *mfi;
|
||||||
int ret;
|
int ret;
|
||||||
@ -538,7 +539,7 @@ mpd_add_mediainfo_byid(struct evbuffer *evbuf, int id, int pos_pl)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mpd_add_mediainfo(evbuf, mfi, pos_pl);
|
ret = mpd_add_mediainfo(evbuf, mfi, item_id, pos_pl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Error adding media info for file with id: %d\n", id);
|
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;
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", status.id);
|
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"
|
"nextsong: %d\n"
|
||||||
"nextsongid: %d\n",
|
"nextsongid: %d\n",
|
||||||
status.pos_pl,
|
status.pos_pl,
|
||||||
status.id,
|
status.item_id,
|
||||||
(status.pos_ms / 1000), (status.len_ms / 1000),
|
(status.pos_ms / 1000), (status.len_ms / 1000),
|
||||||
(status.pos_ms / 1000.0),
|
(status.pos_ms / 1000.0),
|
||||||
status.next_pos_pl,
|
status.next_pos_pl,
|
||||||
status.next_id);
|
status.next_item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filescanner_scanning())
|
if (filescanner_scanning())
|
||||||
@ -1210,7 +1211,7 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (songpos > 0)
|
if (songpos > 0)
|
||||||
ret = player_playback_startpos(songpos, NULL);
|
ret = player_playback_start_byindex(songpos, NULL);
|
||||||
else
|
else
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
|
|
||||||
@ -1263,7 +1264,7 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id > 0)
|
if (id > 0)
|
||||||
ret = player_playback_startid(id, NULL);
|
ret = player_playback_start_byitemid(id, NULL);
|
||||||
else
|
else
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
|
|
||||||
@ -1506,6 +1507,37 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return 0;
|
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'
|
* Command handler function for 'add'
|
||||||
* Adds the all songs under the given path to the end of the playqueue (directories add recursively).
|
* 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
|
static int
|
||||||
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
@ -1525,9 +1557,9 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_ARG;
|
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]);
|
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1535,7 +1567,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1555,7 +1587,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
static int
|
static int
|
||||||
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
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");
|
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]);
|
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||||
if (ret < 0)
|
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,
|
evbuffer_add_printf(evbuf,
|
||||||
"addid: %s\n"
|
"addid: %s\n"
|
||||||
"Id: %d\n",
|
"Id: %d\n",
|
||||||
argv[1],
|
argv[1],
|
||||||
ps->id);
|
0); //ps->id);
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
if (ret < 0)
|
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 argv[1] is ommited clear the whole queue except the current playing one
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
player_queue_empty(0);
|
player_queue_clear();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,7 +1697,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_ARG;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_queue_remove(pos);
|
ret = player_queue_remove_bypos(pos);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to remove song at position '%d'", pos);
|
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;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_queue_removeid(songid);
|
ret = player_queue_remove_byitemid(songid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to remove song with id '%s'", argv[1]);
|
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
|
static int
|
||||||
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
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;
|
uint32_t songid;
|
||||||
int pos_pl;
|
int pos_pl;
|
||||||
|
int count;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
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)
|
// 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)
|
if (!queue)
|
||||||
{
|
{
|
||||||
@ -1754,15 +1789,17 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl = queue->start_pos;
|
pos_pl = 0;
|
||||||
for (i = 0; i < queue->count; i++)
|
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)
|
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);
|
queue_free(queue);
|
||||||
|
|
||||||
@ -1791,15 +1828,17 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
|||||||
static int
|
static int
|
||||||
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
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 start_pos;
|
||||||
int end_pos;
|
int end_pos;
|
||||||
|
int count;
|
||||||
int pos_pl;
|
int pos_pl;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
start_pos = 0;
|
start_pos = 0;
|
||||||
end_pos = -1;
|
end_pos = 0;
|
||||||
|
|
||||||
if (argc > 1)
|
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)
|
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]);
|
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;
|
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)
|
if (!queue)
|
||||||
{
|
{
|
||||||
@ -1827,13 +1869,15 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl = queue->start_pos;
|
pos_pl = start_pos;
|
||||||
for (i = 0; i < queue->count; i++)
|
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)
|
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);
|
queue_free(queue);
|
||||||
|
|
||||||
@ -1857,8 +1901,10 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||||||
static int
|
static int
|
||||||
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
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 pos_pl;
|
||||||
|
int count;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
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,
|
* 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.
|
* 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)
|
if (!queue)
|
||||||
{
|
{
|
||||||
@ -1874,13 +1920,15 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl = queue->start_pos;
|
pos_pl = 0;
|
||||||
for (i = 0; i < queue->count; i++)
|
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)
|
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);
|
queue_free(queue);
|
||||||
|
|
||||||
@ -2106,8 +2154,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct playlist_info *pli;
|
struct playlist_info *pli;
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
uint32_t pos;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
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
|
//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);
|
free_pli(pli, 0);
|
||||||
|
|
||||||
@ -2150,7 +2197,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2387,7 +2434,7 @@ static int
|
|||||||
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
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);
|
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");
|
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2416,7 +2463,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
if (ret < 0)
|
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);
|
mfi = db_file_fetch_byvirtualpath(fi->virtual_path);
|
||||||
if (mfi)
|
if (mfi)
|
||||||
{
|
{
|
||||||
ret = mpd_add_mediainfo(evbuf, mfi, -1);
|
ret = mpd_add_mediainfo(evbuf, mfi, 0, -1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Could not add mediainfo for path '%s'\n", fi->virtual_path);
|
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)
|
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct player_source *ps;
|
struct queue_item *items;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
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);
|
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");
|
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2890,7 +2937,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(ps);
|
player_queue_add(items);
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start(NULL);
|
||||||
if (ret < 0)
|
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 <stdint.h>
|
||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
/* AirTunes v2 packet interval in ns */
|
/* AirTunes v2 packet interval in ns */
|
||||||
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
|
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
|
||||||
@ -27,12 +28,6 @@ enum play_status {
|
|||||||
PLAY_PLAYING = 4,
|
PLAY_PLAYING = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum repeat_mode {
|
|
||||||
REPEAT_OFF = 0,
|
|
||||||
REPEAT_SONG = 1,
|
|
||||||
REPEAT_ALL = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct spk_flags {
|
struct spk_flags {
|
||||||
unsigned selected:1;
|
unsigned selected:1;
|
||||||
unsigned has_password:1;
|
unsigned has_password:1;
|
||||||
@ -56,8 +51,10 @@ struct player_status {
|
|||||||
uint32_t plversion;
|
uint32_t plversion;
|
||||||
/* Playlist length */
|
/* Playlist length */
|
||||||
uint32_t playlistlength;
|
uint32_t playlistlength;
|
||||||
/* Playing song id*/
|
/* Id of the playing file/item in the files database */
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
/* Item-Id of the playing file/item in the queue */
|
||||||
|
uint32_t item_id;
|
||||||
/* Elapsed time in ms of playing item */
|
/* Elapsed time in ms of playing item */
|
||||||
uint32_t pos_ms;
|
uint32_t pos_ms;
|
||||||
/* Length in ms of playing item */
|
/* Length in ms of playing item */
|
||||||
@ -66,51 +63,14 @@ struct player_status {
|
|||||||
int pos_pl;
|
int pos_pl;
|
||||||
/* Item id of next item in playlist */
|
/* Item id of next item in playlist */
|
||||||
uint32_t next_id;
|
uint32_t next_id;
|
||||||
|
/* Item-Id of the next file/item in the queue */
|
||||||
|
uint32_t next_item_id;
|
||||||
/* Playlist position of next item */
|
/* Playlist position of next item */
|
||||||
int next_pos_pl;
|
int next_pos_pl;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg);
|
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
|
struct player_history
|
||||||
{
|
{
|
||||||
/* Buffer index of the oldest remembered song */
|
/* Buffer index of the oldest remembered song */
|
||||||
@ -121,6 +81,7 @@ struct player_history
|
|||||||
|
|
||||||
/* Circular buffer of song ids previously played by forked-daapd */
|
/* Circular buffer of song ids previously played by forked-daapd */
|
||||||
uint32_t id[MAX_HISTORY_COUNT];
|
uint32_t id[MAX_HISTORY_COUNT];
|
||||||
|
uint32_t item_id[MAX_HISTORY_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -143,13 +104,16 @@ int
|
|||||||
player_speaker_set(uint64_t *ids);
|
player_speaker_set(uint64_t *ids);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_playback_start(uint32_t *idx_id);
|
player_playback_start(uint32_t *id);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_playback_startpos(int pos, uint32_t *itemid);
|
player_playback_start_byindex(int pos, uint32_t *id);
|
||||||
|
|
||||||
int
|
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
|
int
|
||||||
player_playback_stop(void);
|
player_playback_stop(void);
|
||||||
@ -182,48 +146,38 @@ player_repeat_set(enum repeat_mode mode);
|
|||||||
int
|
int
|
||||||
player_shuffle_set(int enable);
|
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
|
int
|
||||||
player_queue_make_daap(struct player_source **head, const char *query, const char *queuefilter, const char *sort, int quirk);
|
player_queue_add(struct queue_item *items);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
player_queue_add(struct player_source *ps);
|
player_queue_add_next(struct queue_item *items);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_queue_add_next(struct player_source *ps);
|
player_queue_move_bypos(int ps_pos_from, int ps_pos_to);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_queue_move(int ps_pos_from, int ps_pos_to);
|
player_queue_remove_bypos(int pos);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_queue_remove(int ps_pos_remove);
|
player_queue_remove_byitemid(uint32_t id);
|
||||||
|
|
||||||
int
|
|
||||||
player_queue_removeid(uint32_t id);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
player_queue_clear(void);
|
player_queue_clear(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
player_queue_empty(int clear_hist);
|
player_queue_clear_history(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
player_queue_plid(uint32_t plid);
|
player_queue_plid(uint32_t plid);
|
||||||
|
|
||||||
|
|
||||||
struct player_history *
|
struct player_history *
|
||||||
player_history_get(void);
|
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
|
static int
|
||||||
playback_play(struct spotify_command *cmd)
|
playback_setup(struct spotify_command *cmd)
|
||||||
{
|
{
|
||||||
sp_track *track;
|
sp_track *track;
|
||||||
sp_error err;
|
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))
|
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();
|
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);
|
err = fptr_sp_session_player_play(g_sess, 1);
|
||||||
if (SP_ERROR_OK != err)
|
if (SP_ERROR_OK != err)
|
||||||
{
|
{
|
||||||
@ -980,25 +990,6 @@ playback_pause(struct spotify_command *cmd)
|
|||||||
return 0;
|
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
|
static int
|
||||||
playback_stop(struct spotify_command *cmd)
|
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 spotify was paused begin by resuming playback
|
||||||
if (g_state == SPOTIFY_STATE_PAUSED)
|
if (g_state == SPOTIFY_STATE_PAUSED)
|
||||||
playback_resume(NULL);
|
playback_play(NULL);
|
||||||
|
|
||||||
pthread_mutex_lock(&g_audio_fifo->mutex);
|
pthread_mutex_lock(&g_audio_fifo->mutex);
|
||||||
|
|
||||||
@ -1626,13 +1617,13 @@ notify_cb(int fd, short what, void *arg)
|
|||||||
|
|
||||||
/* Thread: player */
|
/* Thread: player */
|
||||||
int
|
int
|
||||||
spotify_playback_play(struct media_file_info *mfi)
|
spotify_playback_setup(struct media_file_info *mfi)
|
||||||
{
|
{
|
||||||
struct spotify_command cmd;
|
struct spotify_command cmd;
|
||||||
sp_link *link;
|
sp_link *link;
|
||||||
int ret;
|
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);
|
link = fptr_sp_link_create_from_string(mfi->path);
|
||||||
if (!link)
|
if (!link)
|
||||||
@ -1643,7 +1634,7 @@ spotify_playback_play(struct media_file_info *mfi)
|
|||||||
|
|
||||||
command_init(&cmd);
|
command_init(&cmd);
|
||||||
|
|
||||||
cmd.func = playback_play;
|
cmd.func = playback_setup;
|
||||||
cmd.arg.link = link;
|
cmd.arg.link = link;
|
||||||
|
|
||||||
ret = sync_command(&cmd);
|
ret = sync_command(&cmd);
|
||||||
@ -1653,6 +1644,46 @@ spotify_playback_play(struct media_file_info *mfi)
|
|||||||
return ret;
|
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 */
|
/* Thread: libspotify */
|
||||||
void
|
void
|
||||||
spotify_playback_pause_nonblock(void)
|
spotify_playback_pause_nonblock(void)
|
||||||
@ -1678,27 +1709,6 @@ spotify_playback_pause_nonblock(void)
|
|||||||
nonblock_command(cmd);
|
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 */
|
/* Thread: player and libspotify */
|
||||||
int
|
int
|
||||||
spotify_playback_stop(void)
|
spotify_playback_stop(void)
|
||||||
|
@ -11,7 +11,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
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
|
void
|
||||||
spotify_playback_pause_nonblock(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->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;
|
ctx->wavhdr = wavhdr;
|
||||||
|
|
||||||
if (wavhdr)
|
if (wavhdr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user