Playlist queue patch (http://musicpd.org/mantis/view.php?id=1478) version 11.
This adds the following commands: * queueid <id> Add song <id> to the queue. * dequeue <pos> Remove song from <pos> from the queue * queueinfo List the queue To the statusfield it adds the following entry: playlistqueue: <uid> UID can be used by clients to track changes in the playlist queue. git-svn-id: https://svn.musicpd.org/mpd/trunk@6927 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
3a03b89b48
commit
cb9d1b3d27
@ -98,6 +98,9 @@
|
||||
#define COMMAND_PLAYLISTSEARCH "playlistsearch"
|
||||
#define COMMAND_PLAYLISTMOVE "playlistmove"
|
||||
#define COMMAND_PLAYLISTDELETE "playlistdelete"
|
||||
#define COMMAND_QUEUEID "queueid"
|
||||
#define COMMAND_DEQUEUE "dequeue"
|
||||
#define COMMAND_QUEUEINFO "queueinfo"
|
||||
#define COMMAND_TAGTYPES "tagtypes"
|
||||
#define COMMAND_COUNT "count"
|
||||
#define COMMAND_RENAME "rename"
|
||||
@ -107,6 +110,7 @@
|
||||
#define COMMAND_STATUS_REPEAT "repeat"
|
||||
#define COMMAND_STATUS_RANDOM "random"
|
||||
#define COMMAND_STATUS_PLAYLIST "playlist"
|
||||
#define COMMAND_STATUS_PLAYLIST_QUEUE "playlistqueue"
|
||||
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
|
||||
#define COMMAND_STATUS_SONG "song"
|
||||
#define COMMAND_STATUS_SONGID "songid"
|
||||
@ -278,6 +282,8 @@ static int commandStatus(int fd, int *permission, int argc, char *argv[])
|
||||
getPlaylistRandomStatus());
|
||||
fdprintf(fd, "%s: %li\n", COMMAND_STATUS_PLAYLIST,
|
||||
getPlaylistVersion());
|
||||
fdprintf(fd, "%s: %li\n", COMMAND_STATUS_PLAYLIST_QUEUE,
|
||||
getPlaylistQueueVersion());
|
||||
fdprintf(fd, "%s: %i\n", COMMAND_STATUS_PLAYLIST_LENGTH,
|
||||
getPlaylistLength());
|
||||
fdprintf(fd, "%s: %i\n", COMMAND_STATUS_CROSSFADE,
|
||||
@ -625,6 +631,47 @@ static int handlePlaylistMove(int fd, int *permission, int argc, char *argv[])
|
||||
return moveSongInStoredPlaylistByPath(fd, playlist, from, to);
|
||||
}
|
||||
|
||||
static int handleQueueInfo(int fd, int *permission, int argc, char *argv[])
|
||||
{
|
||||
return playlistQueueInfo(fd);
|
||||
}
|
||||
|
||||
static int handleQueueId(int fd, int *permission, int argc, char *argv[])
|
||||
{
|
||||
int id, position = -1;
|
||||
char *test;
|
||||
|
||||
id = strtol(argv[1], &test, 10);
|
||||
if (*test != '\0') {
|
||||
commandError(fd, ACK_ERROR_ARG,
|
||||
"\"%s\" is not a integer", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (argc == 3) {
|
||||
position = strtol(argv[2], &test, 10);
|
||||
if (*test != '\0') {
|
||||
commandError(fd, ACK_ERROR_ARG,
|
||||
"\"%s\" is not a integer", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return addToPlaylistQueueById(fd, id, position);
|
||||
}
|
||||
|
||||
static int handleDequeue(int fd, int *permission, int argc, char *argv[])
|
||||
{
|
||||
int pos;
|
||||
char *test;
|
||||
|
||||
pos = strtol(argv[1], &test, 10);
|
||||
if (*test != '\0') {
|
||||
commandError(fd, ACK_ERROR_ARG,
|
||||
"\"%s\" is not a integer", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
return deleteFromPlaylistQueue(fd, pos);
|
||||
}
|
||||
|
||||
static int listHandleUpdate(int fd,
|
||||
int *permission,
|
||||
int argc,
|
||||
@ -1121,6 +1168,9 @@ void initCommands(void)
|
||||
addCommand(COMMAND_PLAYLISTSEARCH, PERMISSION_READ, 2, -1, handlePlaylistSearch, NULL);
|
||||
addCommand(COMMAND_PLAYLISTMOVE, PERMISSION_CONTROL, 3, 3, handlePlaylistMove, NULL);
|
||||
addCommand(COMMAND_PLAYLISTDELETE, PERMISSION_CONTROL, 2, 2, handlePlaylistDelete, NULL);
|
||||
addCommand(COMMAND_QUEUEINFO, PERMISSION_CONTROL, 0, 0, handleQueueInfo, NULL);
|
||||
addCommand(COMMAND_QUEUEID, PERMISSION_CONTROL, 1, 2, handleQueueId, NULL);
|
||||
addCommand(COMMAND_DEQUEUE, PERMISSION_CONTROL, 1, 1, handleDequeue, NULL);
|
||||
addCommand(COMMAND_TAGTYPES, PERMISSION_READ, 0, 0, handleTagTypes, NULL);
|
||||
addCommand(COMMAND_COUNT, PERMISSION_READ, 2, -1, handleCount, NULL);
|
||||
addCommand(COMMAND_RENAME, PERMISSION_CONTROL, 2, 2, handleRename, NULL);
|
||||
|
15
src/list.c
15
src/list.c
@ -287,6 +287,21 @@ int findInList(List * list, char *key, void **data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListNode *getNodeByPosition(List *list, int pos)
|
||||
{
|
||||
ListNode *tmpNode;
|
||||
|
||||
assert(list != NULL);
|
||||
if (pos < 0 || pos >= list->numberOfNodes)
|
||||
return NULL;
|
||||
|
||||
tmpNode = list->firstNode;
|
||||
while (pos-- > 0)
|
||||
tmpNode = tmpNode->nextNode;
|
||||
|
||||
return tmpNode;
|
||||
}
|
||||
|
||||
int deleteFromList(List * list, char *key)
|
||||
{
|
||||
ListNode *tmpNode;
|
||||
|
@ -100,6 +100,12 @@ int findInList(List * list, char *key, void **data);
|
||||
the info would be found */
|
||||
int findNodeInList(List * list, char *key, ListNode ** node, int *pos);
|
||||
|
||||
/*
|
||||
* returns ListNode at position _pos_ from first node. If no ListNode exists
|
||||
* at position _pos_ returns NULL
|
||||
*/
|
||||
ListNode *getNodeByPosition(List *list, int pos);
|
||||
|
||||
/* frees memory malloc'd for list and its nodes
|
||||
* _list_ -> List to be free'd
|
||||
*/
|
||||
|
173
src/playlist.c
173
src/playlist.c
@ -73,9 +73,12 @@ static int playlist_noGoToNext;
|
||||
|
||||
int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
|
||||
|
||||
static List *playlistQueue;
|
||||
|
||||
static void swapOrder(int a, int b);
|
||||
static int playPlaylistOrderNumber(int fd, int orderNum);
|
||||
static void randomizeOrder(int start, int end);
|
||||
static void clearPlayerQueue(void);
|
||||
|
||||
static void incrPlaylistVersion(void)
|
||||
{
|
||||
@ -103,6 +106,14 @@ void playlistVersionChange(void)
|
||||
incrPlaylistVersion();
|
||||
}
|
||||
|
||||
static void incrPlaylistQueueVersion(void)
|
||||
{
|
||||
static unsigned long max = ((mpd_uint32) 1 << 31) - 1;
|
||||
playlist.queueversion++;
|
||||
if (playlist.queueversion >= max)
|
||||
playlist.queueversion = 1;
|
||||
}
|
||||
|
||||
static void incrPlaylistCurrent(void)
|
||||
{
|
||||
if (playlist.current < 0)
|
||||
@ -126,6 +137,7 @@ void initPlaylist(void)
|
||||
playlist.length = 0;
|
||||
playlist.repeat = 0;
|
||||
playlist.version = 1;
|
||||
playlist.queueversion = 1;
|
||||
playlist.random = 0;
|
||||
playlist.queued = -1;
|
||||
playlist.current = -1;
|
||||
@ -160,6 +172,8 @@ void initPlaylist(void)
|
||||
for (i = 0; i < playlist_max_length * PLAYLIST_HASH_MULT; i++) {
|
||||
playlist.idToPosition[i] = -1;
|
||||
}
|
||||
|
||||
playlistQueue = makeList(DEFAULT_FREE_DATA_FUNC, 0);
|
||||
}
|
||||
|
||||
static int getNextId(void)
|
||||
@ -205,6 +219,7 @@ int clearPlaylist(int fd)
|
||||
|
||||
if (stopPlaylist(fd) < 0)
|
||||
return -1;
|
||||
clearPlaylistQueue();
|
||||
|
||||
for (i = 0; i < playlist.length; i++) {
|
||||
if (playlist.songs[i]->type == SONG_TYPE_URL) {
|
||||
@ -485,7 +500,28 @@ static void swapSongs(int song1, int song2)
|
||||
|
||||
static void queueNextSongInPlaylist(void)
|
||||
{
|
||||
if (playlist.current < playlist.length - 1) {
|
||||
if (playlistQueue->numberOfNodes != 0) {
|
||||
int i;
|
||||
/* we need to find where in order[] is first song from queue */
|
||||
for (i=0;i < playlist.length; i++)
|
||||
if (playlist.order[i] == playlist.
|
||||
idToPosition[*(int *)playlistQueue->
|
||||
firstNode->data])
|
||||
break;
|
||||
clearPlayerQueue();
|
||||
playlist.queued = i;
|
||||
DEBUG("playlist: queue song %i:\"%s\"\n",
|
||||
playlist.queued,
|
||||
getSongUrl(playlist.
|
||||
songs[playlist.order[playlist.queued]]));
|
||||
|
||||
if (queueSong(playlist.songs[playlist.order[playlist.queued]]) <
|
||||
0) {
|
||||
playlist.queued = -1;
|
||||
playlist_queueError = 1;
|
||||
}
|
||||
} else if (playlist.current < playlist.length - 1) {
|
||||
clearPlayerQueue();
|
||||
playlist.queued = playlist.current + 1;
|
||||
DEBUG("playlist: queue song %i:\"%s\"\n",
|
||||
playlist.queued,
|
||||
@ -500,6 +536,7 @@ static void queueNextSongInPlaylist(void)
|
||||
if (playlist.length > 1 && playlist.random) {
|
||||
randomizeOrder(0, playlist.length - 1);
|
||||
}
|
||||
clearPlayerQueue();
|
||||
playlist.queued = 0;
|
||||
DEBUG("playlist: queue song %i:\"%s\"\n",
|
||||
playlist.queued,
|
||||
@ -527,6 +564,9 @@ static void syncPlaylistWithQueue(int queue)
|
||||
if (playlist.queued >= 0) {
|
||||
DEBUG("playlist: now playing queued song\n");
|
||||
playlist.current = playlist.queued;
|
||||
if (playlistQueue->numberOfNodes > 0) {
|
||||
deleteFromPlaylistQueueInternal(0);
|
||||
}
|
||||
}
|
||||
playlist.queued = -1;
|
||||
if (queue)
|
||||
@ -737,12 +777,29 @@ int deleteFromPlaylist(int fd, int song)
|
||||
{
|
||||
int i;
|
||||
int songOrder;
|
||||
ListNode *qItem;
|
||||
|
||||
if (song < 0 || song >= playlist.length) {
|
||||
commandError(fd, ACK_ERROR_NO_EXIST,
|
||||
"song doesn't exist: \"%i\"", song);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we need to clear song from queue */
|
||||
i = 0;
|
||||
qItem = playlistQueue->firstNode;
|
||||
while (qItem) {
|
||||
if (playlist.idToPosition[*(int *)qItem->data] ==
|
||||
song) {
|
||||
|
||||
qItem = qItem->nextNode;
|
||||
deleteFromPlaylistQueueInternal(i);
|
||||
/* can be queued multiple times */
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
qItem = qItem->nextNode;
|
||||
}
|
||||
|
||||
if (playlist_state == PLAYLIST_STATE_PLAY) {
|
||||
if (playlist.queued >= 0
|
||||
@ -859,9 +916,28 @@ static int playPlaylistOrderNumber(int fd, int orderNum)
|
||||
|
||||
playlist.current = orderNum;
|
||||
|
||||
/* are we playing from queue ? */
|
||||
if (playlistQueue->numberOfNodes > 0 &&
|
||||
playlist.idToPosition[*(int *)playlistQueue->
|
||||
firstNode->data] == playlist.order[orderNum]) {
|
||||
deleteFromPlaylistQueueInternal(0);
|
||||
queueNextSongInPlaylist();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int playNextPlaylistQueue(int fd, int stopOnError)
|
||||
{
|
||||
int ret;
|
||||
if (playlistQueue->numberOfNodes == 0)
|
||||
return -1;
|
||||
|
||||
ret = playPlaylistById(fd, *(int *)playlistQueue->firstNode->data,
|
||||
stopOnError);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int playPlaylist(int fd, int song, int stopOnError)
|
||||
{
|
||||
int i = song;
|
||||
@ -875,6 +951,12 @@ int playPlaylist(int fd, int song, int stopOnError)
|
||||
if (playlist_state == PLAYLIST_STATE_PLAY) {
|
||||
return playerSetPause(fd, 0);
|
||||
}
|
||||
|
||||
if (playlist_state != PLAYLIST_STATE_STOP &&
|
||||
playNextPlaylistQueue(fd, stopOnError) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (playlist.current >= 0 && playlist.current < playlist.length) {
|
||||
i = playlist.current;
|
||||
} else {
|
||||
@ -982,6 +1064,9 @@ int nextSongInPlaylist(int fd)
|
||||
|
||||
playlist_stopOnError = 0;
|
||||
|
||||
if (playNextPlaylistQueue(fd, 0) == 0)
|
||||
return 0;
|
||||
|
||||
if (playlist.current < playlist.length - 1) {
|
||||
return playPlaylistOrderNumber(fd, playlist.current + 1);
|
||||
} else if (playlist.length && playlist.repeat) {
|
||||
@ -1349,6 +1434,11 @@ unsigned long getPlaylistVersion(void)
|
||||
return playlist.version;
|
||||
}
|
||||
|
||||
unsigned long getPlaylistQueueVersion(void)
|
||||
{
|
||||
return playlist.queueversion;
|
||||
}
|
||||
|
||||
int getPlaylistLength(void)
|
||||
{
|
||||
return playlist.length;
|
||||
@ -1496,3 +1586,84 @@ void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items)
|
||||
printPlaylistSongInfo(fd, i);
|
||||
}
|
||||
}
|
||||
|
||||
void clearPlaylistQueue(void)
|
||||
{
|
||||
freeList(playlistQueue);
|
||||
playlistQueue = makeList(DEFAULT_FREE_DATA_FUNC, 0);
|
||||
incrPlaylistQueueVersion();
|
||||
}
|
||||
|
||||
int addToPlaylistQueueById(int fd, int song, int toPosition)
|
||||
{
|
||||
int pos, *data;
|
||||
ListNode *prevItem;
|
||||
|
||||
pos = playlist.idToPosition[song];
|
||||
if (pos < 0 || pos >= playlist.length) {
|
||||
commandError(fd, ACK_ERROR_NO_EXIST,
|
||||
"song doesn't exist: \"%i\"", song);
|
||||
return -1;
|
||||
}
|
||||
if (toPosition < -1 || toPosition > playlistQueue->numberOfNodes) {
|
||||
commandError(fd, ACK_ERROR_ARG,
|
||||
"queue position out of range: \"%i\"", toPosition);
|
||||
return -1;
|
||||
}
|
||||
data = xmalloc(sizeof(int));
|
||||
*data = song;
|
||||
if (toPosition == -1) {
|
||||
insertInList(playlistQueue, (char *)1, data);
|
||||
} else {
|
||||
prevItem = getNodeByPosition(playlistQueue, toPosition);
|
||||
if (prevItem == NULL) {
|
||||
insertInList(playlistQueue, (char *)1, data);
|
||||
} else
|
||||
insertInListBeforeNode(playlistQueue, prevItem, -1,
|
||||
(char*) 1, data);
|
||||
}
|
||||
|
||||
if (playlistQueue->numberOfNodes == 1 || toPosition == 0)
|
||||
queueNextSongInPlaylist();
|
||||
incrPlaylistQueueVersion();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deleteFromPlaylistQueue(int fd, int song)
|
||||
{
|
||||
if (song < 0 || song >= playlistQueue->numberOfNodes) {
|
||||
commandError(fd, ACK_ERROR_NO_EXIST,
|
||||
"song doesn't exist: \"%i\"", song);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return deleteFromPlaylistQueueInternal(song);
|
||||
}
|
||||
|
||||
int deleteFromPlaylistQueueInternal(int song)
|
||||
{
|
||||
ListNode *delItem;
|
||||
|
||||
delItem = getNodeByPosition(playlistQueue, song);
|
||||
if (delItem == NULL)
|
||||
return -1;
|
||||
|
||||
deleteNodeFromList(playlistQueue, delItem);
|
||||
if (song == 0)
|
||||
queueNextSongInPlaylist();
|
||||
|
||||
incrPlaylistQueueVersion();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int playlistQueueInfo(int fd)
|
||||
{
|
||||
ListNode *cur = playlistQueue->firstNode;
|
||||
int no = 0;
|
||||
while (cur) {
|
||||
printSongInfo(fd, playlist.songs[playlist.idToPosition[*(int *)cur->data]]);
|
||||
fdprintf(fd, "Pos: %i\nId: %i\n", no++, *(int *)cur->data);
|
||||
cur = cur->nextNode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ typedef struct _Playlist {
|
||||
int repeat;
|
||||
int random;
|
||||
mpd_uint32 version;
|
||||
mpd_uint32 queueversion;
|
||||
} Playlist;
|
||||
|
||||
extern int playlist_saveAbsolutePaths;
|
||||
@ -79,6 +80,8 @@ int stopPlaylist(int fd);
|
||||
|
||||
int playPlaylist(int fd, int song, int stopOnError);
|
||||
|
||||
int playNextPlaylistQueue(int fd, int stopOnError);
|
||||
|
||||
int playPlaylistById(int fd, int song, int stopOnError);
|
||||
|
||||
int nextSongInPlaylist(int fd);
|
||||
@ -123,6 +126,8 @@ int getPlaylistLength(void);
|
||||
|
||||
unsigned long getPlaylistVersion(void);
|
||||
|
||||
unsigned long getPlaylistQueueVersion(void);
|
||||
|
||||
void playPlaylistIfPlayerStopped(void);
|
||||
|
||||
int seekSongInPlaylist(int fd, int song, float time);
|
||||
@ -141,4 +146,14 @@ void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items);
|
||||
|
||||
void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items);
|
||||
|
||||
void clearPlaylistQueue(void);
|
||||
|
||||
int addToPlaylistQueueById(int fd, int song, int toPosition);
|
||||
|
||||
int deleteFromPlaylistQueue(int fd, int song);
|
||||
|
||||
int deleteFromPlaylistQueueInternal(int song);
|
||||
|
||||
int playlistQueueInfo(int fd);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user