aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/src/playlist.c
diff options
context:
space:
mode:
authorJ. Alexander Treuman <jat@spatialrift.net>2007-05-28 15:50:45 +0000
committerJ. Alexander Treuman <jat@spatialrift.net>2007-05-28 15:50:45 +0000
commit4e05a161e54fe05902b99eff521aa0759b102f05 (patch)
tree9014ab8ce74e4fb2f0115c5518c62879bc269324 /trunk/src/playlist.c
parente45bc035931b2c9ef13b85f98a3d4833a8dec8a9 (diff)
downloadmpd-4e05a161e54fe05902b99eff521aa0759b102f05.tar.gz
mpd-4e05a161e54fe05902b99eff521aa0759b102f05.tar.xz
mpd-4e05a161e54fe05902b99eff521aa0759b102f05.zip
Making branch for 0.13.0 fixes.
git-svn-id: https://svn.musicpd.org/mpd/branches/branch-0.13.0-fixes@6330 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to 'trunk/src/playlist.c')
-rw-r--r--trunk/src/playlist.c1499
1 files changed, 0 insertions, 1499 deletions
diff --git a/trunk/src/playlist.c b/trunk/src/playlist.c
deleted file mode 100644
index d8f2c6b65..000000000
--- a/trunk/src/playlist.c
+++ /dev/null
@@ -1,1499 +0,0 @@
-/* the Music Player Daemon (MPD)
- * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
- * This project's homepage is: http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "playlist.h"
-#include "player.h"
-#include "command.h"
-#include "ls.h"
-#include "tag.h"
-#include "conf.h"
-#include "directory.h"
-#include "log.h"
-#include "path.h"
-#include "utils.h"
-#include "sig_handlers.h"
-#include "state_file.h"
-#include "storedPlaylist.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-
-#define PLAYLIST_STATE_STOP 0
-#define PLAYLIST_STATE_PLAY 1
-
-#define PLAYLIST_PREV_UNLESS_ELAPSED 10
-
-#define PLAYLIST_STATE_FILE_STATE "state: "
-#define PLAYLIST_STATE_FILE_RANDOM "random: "
-#define PLAYLIST_STATE_FILE_REPEAT "repeat: "
-#define PLAYLIST_STATE_FILE_CURRENT "current: "
-#define PLAYLIST_STATE_FILE_TIME "time: "
-#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: "
-#define PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "playlist_begin"
-#define PLAYLIST_STATE_FILE_PLAYLIST_END "playlist_end"
-
-#define PLAYLIST_STATE_FILE_STATE_PLAY "play"
-#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause"
-#define PLAYLIST_STATE_FILE_STATE_STOP "stop"
-
-#define PLAYLIST_BUFFER_SIZE 2*MAXPATHLEN
-
-#define PLAYLIST_HASH_MULT 4
-
-#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
-#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0
-
-static Playlist playlist;
-static int playlist_state = PLAYLIST_STATE_STOP;
-static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH;
-static int playlist_stopOnError;
-static int playlist_errorCount;
-static int playlist_queueError;
-static int playlist_noGoToNext;
-
-int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
-
-static void swapOrder(int a, int b);
-static int playPlaylistOrderNumber(int fd, int orderNum);
-static void randomizeOrder(int start, int end);
-
-static void incrPlaylistVersion(void)
-{
- static unsigned long max = ((mpd_uint32) 1 << 31) - 1;
- playlist.version++;
- if (playlist.version >= max) {
- int i;
-
- for (i = 0; i < playlist.length; i++) {
- playlist.songMod[i] = 0;
- }
-
- playlist.version = 1;
- }
-}
-
-void playlistVersionChange(void)
-{
- int i = 0;
-
- for (i = 0; i < playlist.length; i++) {
- playlist.songMod[i] = playlist.version;
- }
-
- incrPlaylistVersion();
-}
-
-static void incrPlaylistCurrent(void)
-{
- if (playlist.current < 0)
- return;
-
- if (playlist.current >= playlist.length - 1) {
- if (playlist.repeat)
- playlist.current = 0;
- else
- playlist.current = -1;
- } else
- playlist.current++;
-}
-
-void initPlaylist(void)
-{
- char *test;
- int i;
- ConfigParam *param;
-
- playlist.length = 0;
- playlist.repeat = 0;
- playlist.version = 1;
- playlist.random = 0;
- playlist.queued = -1;
- playlist.current = -1;
-
- param = getConfigParam(CONF_MAX_PLAYLIST_LENGTH);
-
- if (param) {
- playlist_max_length = strtol(param->value, &test, 10);
- if (*test != '\0') {
- FATAL("max playlist length \"%s\" is not an integer, "
- "line %i\n", param->value, param->line);
- }
- }
-
- playlist_saveAbsolutePaths = getBoolConfigParam(CONF_SAVE_ABSOLUTE_PATHS);
- if (playlist_saveAbsolutePaths == -1) playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
- else if (playlist_saveAbsolutePaths < 0) exit(EXIT_FAILURE);
-
- playlist.songs = xmalloc(sizeof(Song *) * playlist_max_length);
- playlist.songMod = xmalloc(sizeof(mpd_uint32) * playlist_max_length);
- playlist.order = xmalloc(sizeof(int) * playlist_max_length);
- playlist.idToPosition = xmalloc(sizeof(int) * playlist_max_length *
- PLAYLIST_HASH_MULT);
- playlist.positionToId = xmalloc(sizeof(int) * playlist_max_length);
-
- memset(playlist.songs, 0, sizeof(char *) * playlist_max_length);
-
- srandom(time(NULL));
-
- for (i = 0; i < playlist_max_length * PLAYLIST_HASH_MULT; i++) {
- playlist.idToPosition[i] = -1;
- }
-}
-
-static int getNextId(void)
-{
- static int cur = -1;
-
- do {
- cur++;
- if (cur >= playlist_max_length * PLAYLIST_HASH_MULT) {
- cur = 0;
- }
- } while (playlist.idToPosition[cur] != -1);
-
- return cur;
-}
-
-void finishPlaylist(void)
-{
- int i;
- for (i = 0; i < playlist.length; i++) {
- if (playlist.songs[i]->type == SONG_TYPE_URL) {
- freeJustSong(playlist.songs[i]);
- }
- }
-
- playlist.length = 0;
-
- free(playlist.songs);
- playlist.songs = NULL;
- free(playlist.songMod);
- playlist.songMod = NULL;
- free(playlist.order);
- playlist.order = NULL;
- free(playlist.idToPosition);
- playlist.idToPosition = NULL;
- free(playlist.positionToId);
- playlist.positionToId = NULL;
-}
-
-int clearPlaylist(int fd)
-{
- int i;
-
- if (stopPlaylist(fd) < 0)
- return -1;
-
- for (i = 0; i < playlist.length; i++) {
- if (playlist.songs[i]->type == SONG_TYPE_URL) {
- freeJustSong(playlist.songs[i]);
- }
- playlist.idToPosition[playlist.positionToId[i]] = -1;
- playlist.songs[i] = NULL;
- }
- playlist.length = 0;
- playlist.current = -1;
-
- incrPlaylistVersion();
-
- return 0;
-}
-
-int clearStoredPlaylist(int fd, char *utf8file)
-{
- removeAllFromStoredPlaylistByPath(fd, utf8file);
- return 0;
-}
-
-int showPlaylist(int fd)
-{
- int i;
-
- for (i = 0; i < playlist.length; i++) {
- fdprintf(fd, "%i:%s\n", i, getSongUrl(playlist.songs[i]));
- }
-
- return 0;
-}
-
-void savePlaylistState(FILE *fp)
-{
- fprintf(fp, "%s", PLAYLIST_STATE_FILE_STATE);
- switch (playlist_state) {
- case PLAYLIST_STATE_PLAY:
- switch (getPlayerState()) {
- case PLAYER_STATE_PAUSE:
- fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_PAUSE);
- break;
- default:
- fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_PLAY);
- }
- fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CURRENT,
- playlist.order[playlist.current]);
- fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_TIME,
- getPlayerElapsedTime());
- break;
- default:
- fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_STATE_STOP);
- break;
- }
- fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_RANDOM, playlist.random);
- fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_REPEAT, playlist.repeat);
- fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CROSSFADE,
- (int)(getPlayerCrossFade()));
- fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_BEGIN);
- fflush(fp);
- showPlaylist(fileno(fp));
- fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_END);
-}
-
-static void loadPlaylistFromStateFile(FILE *fp, char *buffer,
- int state, int current, int time)
-{
- char *temp;
- int song;
-
- if (!myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp))
- state_file_fatal();
- while (strcmp(buffer, PLAYLIST_STATE_FILE_PLAYLIST_END)) {
- song = atoi(strtok(buffer, ":"));
- if (!(temp = strtok(NULL, "")))
- state_file_fatal();
- if (!addToPlaylist(STDERR_FILENO, temp, 0) && current == song) {
- if (state != PLAYER_STATE_STOP) {
- playPlaylist(STDERR_FILENO,
- playlist.length - 1, 0);
- }
- if (state == PLAYER_STATE_PAUSE) {
- playerPause(STDERR_FILENO);
- }
- if (state != PLAYER_STATE_STOP) {
- seekSongInPlaylist(STDERR_FILENO,
- playlist.length - 1, time);
- }
- }
- if (!myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp))
- state_file_fatal();
- }
-}
-
-void readPlaylistState(FILE *fp)
-{
- int current = -1;
- int time = 0;
- int state = PLAYER_STATE_STOP;
- char buffer[PLAYLIST_BUFFER_SIZE];
-
- while (myFgets(buffer, PLAYLIST_BUFFER_SIZE, fp)) {
- if (strncmp(buffer, PLAYLIST_STATE_FILE_STATE,
- strlen(PLAYLIST_STATE_FILE_STATE)) == 0) {
- if (strcmp(&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]),
- PLAYLIST_STATE_FILE_STATE_PLAY) == 0) {
- state = PLAYER_STATE_PLAY;
- } else
- if (strcmp
- (&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]),
- PLAYLIST_STATE_FILE_STATE_PAUSE)
- == 0) {
- state = PLAYER_STATE_PAUSE;
- }
- } else if (strncmp(buffer, PLAYLIST_STATE_FILE_TIME,
- strlen(PLAYLIST_STATE_FILE_TIME)) == 0) {
- time =
- atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)]));
- } else
- if (strncmp
- (buffer, PLAYLIST_STATE_FILE_REPEAT,
- strlen(PLAYLIST_STATE_FILE_REPEAT)) == 0) {
- if (strcmp
- (&(buffer[strlen(PLAYLIST_STATE_FILE_REPEAT)]),
- "1") == 0) {
- setPlaylistRepeatStatus(STDERR_FILENO, 1);
- } else
- setPlaylistRepeatStatus(STDERR_FILENO, 0);
- } else
- if (strncmp
- (buffer, PLAYLIST_STATE_FILE_CROSSFADE,
- strlen(PLAYLIST_STATE_FILE_CROSSFADE)) == 0) {
- setPlayerCrossFade(atoi
- (&
- (buffer
- [strlen
- (PLAYLIST_STATE_FILE_CROSSFADE)])));
- } else
- if (strncmp
- (buffer, PLAYLIST_STATE_FILE_RANDOM,
- strlen(PLAYLIST_STATE_FILE_RANDOM)) == 0) {
- if (strcmp
- (&
- (buffer
- [strlen(PLAYLIST_STATE_FILE_RANDOM)]),
- "1") == 0) {
- setPlaylistRandomStatus(STDERR_FILENO, 1);
- } else
- setPlaylistRandomStatus(STDERR_FILENO, 0);
- } else if (strncmp(buffer, PLAYLIST_STATE_FILE_CURRENT,
- strlen(PLAYLIST_STATE_FILE_CURRENT))
- == 0) {
- if (strlen(buffer) ==
- strlen(PLAYLIST_STATE_FILE_CURRENT))
- state_file_fatal();
- current = atoi(&(buffer
- [strlen
- (PLAYLIST_STATE_FILE_CURRENT)]));
- } else
- if (strncmp
- (buffer, PLAYLIST_STATE_FILE_PLAYLIST_BEGIN,
- strlen(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN)
- ) == 0) {
- if (state == PLAYER_STATE_STOP)
- current = -1;
- loadPlaylistFromStateFile(fp, buffer, state,
- current, time);
- }
- }
-}
-
-static void printPlaylistSongInfo(int fd, int song)
-{
- printSongInfo(fd, playlist.songs[song]);
- fdprintf(fd, "Pos: %i\nId: %i\n", song, playlist.positionToId[song]);
-}
-
-int playlistChanges(int fd, mpd_uint32 version)
-{
- int i;
-
- for (i = 0; i < playlist.length; i++) {
- if (version > playlist.version ||
- playlist.songMod[i] >= version ||
- playlist.songMod[i] == 0) {
- printPlaylistSongInfo(fd, i);
- }
- }
-
- return 0;
-}
-
-int playlistChangesPosId(int fd, mpd_uint32 version)
-{
- int i;
-
- for (i = 0; i < playlist.length; i++) {
- if (version > playlist.version ||
- playlist.songMod[i] >= version ||
- playlist.songMod[i] == 0) {
- fdprintf(fd, "cpos: %i\nId: %i\n",
- i, playlist.positionToId[i]);
- }
- }
-
- return 0;
-}
-
-int playlistInfo(int fd, int song)
-{
- int i;
- int begin = 0;
- int end = playlist.length;
-
- if (song >= 0) {
- begin = song;
- end = song + 1;
- }
- if (song >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song);
- return -1;
- }
-
- for (i = begin; i < end; i++)
- printPlaylistSongInfo(fd, i);
-
- return 0;
-}
-
-# define checkSongId(id) { \
- if(id < 0 || id >= PLAYLIST_HASH_MULT*playlist_max_length || \
- playlist.idToPosition[id] == -1 ) \
- { \
- commandError(fd, ACK_ERROR_NO_EXIST, \
- "song id doesn't exist: \"%i\"", id); \
- return -1; \
- } \
-}
-
-int playlistId(int fd, int id)
-{
- int i;
- int begin = 0;
- int end = playlist.length;
-
- if (id >= 0) {
- checkSongId(id);
- begin = playlist.idToPosition[id];
- end = begin + 1;
- }
-
- for (i = begin; i < end; i++)
- printPlaylistSongInfo(fd, i);
-
- return 0;
-}
-
-static void swapSongs(int song1, int song2)
-{
- Song *sTemp;
- int iTemp;
-
- sTemp = playlist.songs[song1];
- playlist.songs[song1] = playlist.songs[song2];
- playlist.songs[song2] = sTemp;
-
- playlist.songMod[song1] = playlist.version;
- playlist.songMod[song2] = playlist.version;
-
- playlist.idToPosition[playlist.positionToId[song1]] = song2;
- playlist.idToPosition[playlist.positionToId[song2]] = song1;
-
- iTemp = playlist.positionToId[song1];
- playlist.positionToId[song1] = playlist.positionToId[song2];
- playlist.positionToId[song2] = iTemp;
-}
-
-static void queueNextSongInPlaylist(void)
-{
- if (playlist.current < playlist.length - 1) {
- playlist.queued = playlist.current + 1;
- 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.length && playlist.repeat) {
- if (playlist.length > 1 && playlist.random) {
- randomizeOrder(0, playlist.length - 1);
- }
- playlist.queued = 0;
- 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;
- }
- }
-}
-
-static void syncPlaylistWithQueue(int queue)
-{
- if (queue && getPlayerQueueState() == PLAYER_QUEUE_BLANK) {
- queueNextSongInPlaylist();
- } else if (getPlayerQueueState() == PLAYER_QUEUE_DECODE) {
- if (playlist.queued != -1)
- setQueueState(PLAYER_QUEUE_PLAY);
- else
- setQueueState(PLAYER_QUEUE_STOP);
- } else if (getPlayerQueueState() == PLAYER_QUEUE_EMPTY) {
- setQueueState(PLAYER_QUEUE_BLANK);
- if (playlist.queued >= 0) {
- DEBUG("playlist: now playing queued song\n");
- playlist.current = playlist.queued;
- }
- playlist.queued = -1;
- if (queue)
- queueNextSongInPlaylist();
- }
-}
-
-static void lockPlaylistInteraction(void)
-{
- if (getPlayerQueueState() == PLAYER_QUEUE_PLAY ||
- getPlayerQueueState() == PLAYER_QUEUE_FULL) {
- playerQueueLock();
- syncPlaylistWithQueue(0);
- }
-}
-
-static void unlockPlaylistInteraction(void)
-{
- playerQueueUnlock();
-}
-
-static void clearPlayerQueue(void)
-{
- playlist.queued = -1;
- switch (getPlayerQueueState()) {
- case PLAYER_QUEUE_FULL:
- DEBUG("playlist: dequeue song\n");
- setQueueState(PLAYER_QUEUE_BLANK);
- break;
- case PLAYER_QUEUE_PLAY:
- DEBUG("playlist: stop decoding queued song\n");
- setQueueState(PLAYER_QUEUE_STOP);
- break;
- }
-}
-
-int addToPlaylist(int fd, char *url, int printId)
-{
- Song *song;
-
- DEBUG("add to playlist: %s\n", url);
-
- if ((song = getSongFromDB(url))) {
- } else if (!(isValidRemoteUtf8Url(url) &&
- (song = newSong(url, SONG_TYPE_URL, NULL)))) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "\"%s\" is not in the music db or is "
- "not a valid url", url);
- return -1;
- }
-
- return addSongToPlaylist(fd, song, printId);
-}
-
-int addToStoredPlaylist(int fd, char *url, char *utf8file)
-{
- Song *song;
-
- DEBUG("add to stored playlist: %s\n", url);
-
- song = getSongFromDB(url);
- if (song) {
- appendSongToStoredPlaylistByPath(fd, utf8file, song);
- return 0;
- }
-
- if (!isValidRemoteUtf8Url(url))
- goto fail;
-
- song = newSong(url, SONG_TYPE_URL, NULL);
- if (song) {
- appendSongToStoredPlaylistByPath(fd, utf8file, song);
- freeJustSong(song);
- return 0;
- }
-
-fail:
- commandError(fd, ACK_ERROR_NO_EXIST, "\"%s\" is not in the music db"
- "or is not a valid url", url);
- return -1;
-}
-
-int addSongToPlaylist(int fd, Song * song, int printId)
-{
- int id;
-
- if (playlist.length == playlist_max_length) {
- commandError(fd, ACK_ERROR_PLAYLIST_MAX,
- "playlist is at the max size");
- return -1;
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0
- && playlist.current == playlist.length - 1) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- id = getNextId();
-
- playlist.songs[playlist.length] = song;
- playlist.songMod[playlist.length] = playlist.version;
- playlist.order[playlist.length] = playlist.length;
- playlist.positionToId[playlist.length] = id;
- playlist.idToPosition[playlist.positionToId[playlist.length]] =
- playlist.length;
- playlist.length++;
-
- if (playlist.random) {
- int swap;
- int start;
- /*if(playlist_state==PLAYLIST_STATE_STOP) start = 0;
- else */ if (playlist.queued >= 0)
- start = playlist.queued + 1;
- else
- start = playlist.current + 1;
- if (start < playlist.length) {
- swap = random() % (playlist.length - start);
- swap += start;
- swapOrder(playlist.length - 1, swap);
- }
- }
-
- incrPlaylistVersion();
-
- if (printId)
- fdprintf(fd, "Id: %i\n", id);
-
- return 0;
-}
-
-int swapSongsInPlaylist(int fd, int song1, int song2)
-{
- int queuedSong = -1;
- int currentSong = -1;
-
- if (song1 < 0 || song1 >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song1);
- return -1;
- }
- if (song2 < 0 || song2 >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song2);
- return -1;
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0) {
- queuedSong = playlist.order[playlist.queued];
- }
- currentSong = playlist.order[playlist.current];
-
- if (queuedSong == song1 || queuedSong == song2
- || currentSong == song1 || currentSong == song2) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- swapSongs(song1, song2);
- if (playlist.random) {
- int i;
- int k;
- int j = -1;
- for (i = 0; playlist.order[i] != song1; i++) {
- if (playlist.order[i] == song2)
- j = i;
- }
- k = i;
- for (; j == -1; i++)
- if (playlist.order[i] == song2)
- j = i;
- swapOrder(k, j);
- } else {
- if (playlist.current == song1)
- playlist.current = song2;
- else if (playlist.current == song2)
- playlist.current = song1;
- }
-
- incrPlaylistVersion();
-
- return 0;
-}
-
-int swapSongsInPlaylistById(int fd, int id1, int id2)
-{
- checkSongId(id1);
- checkSongId(id2);
-
- return swapSongsInPlaylist(fd, playlist.idToPosition[id1],
- playlist.idToPosition[id2]);
-}
-
-#define moveSongFromTo(from, to) { \
- playlist.idToPosition[playlist.positionToId[from]] = to; \
- playlist.positionToId[to] = playlist.positionToId[from]; \
- playlist.songs[to] = playlist.songs[from]; \
- playlist.songMod[to] = playlist.version; \
-}
-
-int deleteFromPlaylist(int fd, int song)
-{
- int i;
- int songOrder;
-
- if (song < 0 || song >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song);
- return -1;
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0
- && (playlist.order[playlist.queued] == song
- || playlist.order[playlist.current] == song)) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- if (playlist.songs[song]->type == SONG_TYPE_URL) {
- freeJustSong(playlist.songs[song]);
- }
-
- playlist.idToPosition[playlist.positionToId[song]] = -1;
-
- /* delete song from songs array */
- for (i = song; i < playlist.length - 1; i++) {
- moveSongFromTo(i + 1, i);
- }
- /* now find it in the order array */
- for (i = 0; i < playlist.length - 1; i++) {
- if (playlist.order[i] == song)
- break;
- }
- songOrder = i;
- /* delete the entry from the order array */
- for (; i < playlist.length - 1; i++)
- playlist.order[i] = playlist.order[i + 1];
- /* readjust values in the order array */
- for (i = 0; i < playlist.length - 1; i++) {
- if (playlist.order[i] > song)
- playlist.order[i]--;
- }
- /* now take care of other misc stuff */
- playlist.songs[playlist.length - 1] = NULL;
- playlist.length--;
-
- incrPlaylistVersion();
-
- if (playlist_state != PLAYLIST_STATE_STOP
- && playlist.current == songOrder) {
- /*if(playlist.current>=playlist.length) return playerStop(fd);
- else return playPlaylistOrderNumber(fd,playlist.current); */
- playerStop(STDERR_FILENO);
- playlist_noGoToNext = 1;
- }
-
- if (playlist.current > songOrder) {
- playlist.current--;
- } else if (playlist.current >= playlist.length) {
- incrPlaylistCurrent();
- }
-
- if (playlist.queued > songOrder) {
- playlist.queued--;
- }
-
- return 0;
-}
-
-int deleteFromPlaylistById(int fd, int id)
-{
- checkSongId(id);
-
- return deleteFromPlaylist(fd, playlist.idToPosition[id]);
-}
-
-void deleteASongFromPlaylist(Song * song)
-{
- int i;
-
- if (NULL == playlist.songs)
- return;
-
- for (i = 0; i < playlist.length; i++) {
- if (song == playlist.songs[i]) {
- deleteFromPlaylist(STDERR_FILENO, i);
- }
- }
-}
-
-int stopPlaylist(int fd)
-{
- DEBUG("playlist: stop\n");
- if (playerStop(fd) < 0)
- return -1;
- playerCloseAudio();
- playlist.queued = -1;
- playlist_state = PLAYLIST_STATE_STOP;
- playlist_noGoToNext = 0;
- if (playlist.random)
- randomizeOrder(0, playlist.length - 1);
- return 0;
-}
-
-static int playPlaylistOrderNumber(int fd, int orderNum)
-{
-
- if (playerStop(fd) < 0)
- return -1;
-
- playlist_state = PLAYLIST_STATE_PLAY;
- playlist_noGoToNext = 0;
- playlist.queued = -1;
- playlist_queueError = 0;
-
- DEBUG("playlist: play %i:\"%s\"\n", orderNum,
- getSongUrl(playlist.songs[playlist.order[orderNum]]));
-
- if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) {
- stopPlaylist(fd);
- return -1;
- }
-
- playlist.current = orderNum;
-
- return 0;
-}
-
-int playPlaylist(int fd, int song, int stopOnError)
-{
- int i = song;
-
- clearPlayerError();
-
- if (song == -1) {
- if (playlist.length == 0)
- return 0;
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- return playerSetPause(fd, 0);
- }
- if (playlist.current >= 0 && playlist.current < playlist.length) {
- i = playlist.current;
- } else {
- i = 0;
- }
- } else if (song < 0 || song >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song);
- return -1;
- }
-
- if (playlist.random) {
- if (song == -1 && playlist_state == PLAYLIST_STATE_PLAY) {
- randomizeOrder(0, playlist.length - 1);
- } else {
- if (song >= 0)
- for (i = 0; song != playlist.order[i]; i++) ;
- if (playlist_state == PLAYLIST_STATE_STOP) {
- playlist.current = 0;
- }
- swapOrder(i, playlist.current);
- i = playlist.current;
- }
- }
-
- playlist_stopOnError = stopOnError;
- playlist_errorCount = 0;
-
- return playPlaylistOrderNumber(fd, i);
-}
-
-int playPlaylistById(int fd, int id, int stopOnError)
-{
- if (id == -1) {
- return playPlaylist(fd, id, stopOnError);
- }
-
- checkSongId(id);
-
- return playPlaylist(fd, playlist.idToPosition[id], stopOnError);
-}
-
-static void syncCurrentPlayerDecodeMetadata(void)
-{
- Song *songPlayer = playerCurrentDecodeSong();
- Song *song;
- int songNum;
-
- if (!songPlayer)
- return;
-
- if (playlist_state != PLAYLIST_STATE_PLAY)
- return;
-
- songNum = playlist.order[playlist.current];
- song = playlist.songs[songNum];
-
- if (song->type == SONG_TYPE_URL &&
- 0 == strcmp(getSongUrl(song), songPlayer->url) &&
- !mpdTagsAreEqual(song->tag, songPlayer->tag)) {
- if (song->tag)
- freeMpdTag(song->tag);
- song->tag = mpdTagDup(songPlayer->tag);
- playlist.songMod[songNum] = playlist.version;
- incrPlaylistVersion();
- }
-}
-
-void syncPlayerAndPlaylist(void)
-{
- if (playlist_state != PLAYLIST_STATE_PLAY)
- return;
-
- if (getPlayerState() == PLAYER_STATE_STOP)
- playPlaylistIfPlayerStopped();
- else
- syncPlaylistWithQueue(!playlist_queueError);
-
- syncCurrentPlayerDecodeMetadata();
-}
-
-static int currentSongInPlaylist(int fd)
-{
- if (playlist_state != PLAYLIST_STATE_PLAY)
- return 0;
-
- playlist_stopOnError = 0;
-
- syncPlaylistWithQueue(0);
-
- if (playlist.current >= 0 && playlist.current < playlist.length) {
- return playPlaylistOrderNumber(fd, playlist.current);
- } else
- return stopPlaylist(fd);
-
- return 0;
-}
-
-int nextSongInPlaylist(int fd)
-{
- if (playlist_state != PLAYLIST_STATE_PLAY)
- return 0;
-
- syncPlaylistWithQueue(0);
-
- playlist_stopOnError = 0;
-
- if (playlist.current < playlist.length - 1) {
- return playPlaylistOrderNumber(fd, playlist.current + 1);
- } else if (playlist.length && playlist.repeat) {
- if (playlist.random)
- randomizeOrder(0, playlist.length - 1);
- return playPlaylistOrderNumber(fd, 0);
- } else {
- incrPlaylistCurrent();
- return stopPlaylist(fd);
- }
-
- return 0;
-}
-
-void playPlaylistIfPlayerStopped(void)
-{
- if (getPlayerState() == PLAYER_STATE_STOP) {
- int error = getPlayerError();
-
- if (error == PLAYER_ERROR_NOERROR)
- playlist_errorCount = 0;
- else
- playlist_errorCount++;
-
- if (playlist_state == PLAYLIST_STATE_PLAY
- && ((playlist_stopOnError && error != PLAYER_ERROR_NOERROR)
- || error == PLAYER_ERROR_AUDIO
- || error == PLAYER_ERROR_SYSTEM
- || playlist_errorCount >= playlist.length)) {
- stopPlaylist(STDERR_FILENO);
- } else if (playlist_noGoToNext)
- currentSongInPlaylist(STDERR_FILENO);
- else
- nextSongInPlaylist(STDERR_FILENO);
- }
-}
-
-int getPlaylistRepeatStatus(void)
-{
- return playlist.repeat;
-}
-
-int getPlaylistRandomStatus(void)
-{
- return playlist.random;
-}
-
-int setPlaylistRepeatStatus(int fd, int status)
-{
- if (status != 0 && status != 1) {
- commandError(fd, ACK_ERROR_ARG, "\"%i\" is not 0 or 1", status);
- return -1;
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.repeat && !status && playlist.queued == 0) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- playlist.repeat = status;
-
- return 0;
-}
-
-int moveSongInPlaylist(int fd, int from, int to)
-{
- int i;
- Song *tmpSong;
- int tmpId;
- int queuedSong = -1;
- int currentSong = -1;
-
- if (from < 0 || from >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", from);
- return -1;
- }
-
- if (to < 0 || to >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", to);
- return -1;
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0) {
- queuedSong = playlist.order[playlist.queued];
- }
- currentSong = playlist.order[playlist.current];
- if (queuedSong == from || queuedSong == to
- || currentSong == from || currentSong == to) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- tmpSong = playlist.songs[from];
- tmpId = playlist.positionToId[from];
- /* move songs to one less in from->to */
- for (i = from; i < to; i++) {
- moveSongFromTo(i + 1, i);
- }
- /* move songs to one more in to->from */
- for (i = from; i > to; i--) {
- moveSongFromTo(i - 1, i);
- }
- /* put song at _to_ */
- playlist.idToPosition[tmpId] = to;
- playlist.positionToId[to] = tmpId;
- playlist.songs[to] = tmpSong;
- playlist.songMod[to] = playlist.version;
- /* now deal with order */
- if (playlist.random) {
- for (i = 0; i < playlist.length; i++) {
- if (playlist.order[i] > from && playlist.order[i] <= to) {
- playlist.order[i]--;
- } else if (playlist.order[i] < from &&
- playlist.order[i] >= to) {
- playlist.order[i]++;
- } else if (from == playlist.order[i]) {
- playlist.order[i] = to;
- }
- }
- }
- else
- {
- if (playlist.current == from)
- playlist.current = to;
- else if (playlist.current > from && playlist.current <= to) {
- playlist.current--;
- } else if (playlist.current >= to && playlist.current < from) {
- playlist.current++;
- }
-
- /* this first if statement isn't necessary since the queue
- * would have been cleared out if queued == from */
- if (playlist.queued == from)
- playlist.queued = to;
- else if (playlist.queued > from && playlist.queued <= to) {
- playlist.queued--;
- } else if (playlist.queued>= to && playlist.queued < from) {
- playlist.queued++;
- }
- }
-
- incrPlaylistVersion();
-
- return 0;
-}
-
-int moveSongInPlaylistById(int fd, int id1, int to)
-{
- checkSongId(id1);
-
- return moveSongInPlaylist(fd, playlist.idToPosition[id1], to);
-}
-
-static void orderPlaylist(void)
-{
- int i;
-
- if (playlist.current >= 0 && playlist.current < playlist.length) {
- playlist.current = playlist.order[playlist.current];
- }
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- for (i = 0; i < playlist.length; i++) {
- playlist.order[i] = i;
- }
-
-}
-
-static void swapOrder(int a, int b)
-{
- int bak = playlist.order[a];
- playlist.order[a] = playlist.order[b];
- playlist.order[b] = bak;
-}
-
-static void randomizeOrder(int start, int end)
-{
- int i;
- int ri;
-
- DEBUG("playlist: randomize from %i to %i\n", start, end);
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= start && playlist.queued <= end) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- }
-
- for (i = start; i <= end; i++) {
- ri = random() % (end - start + 1) + start;
- if (ri == playlist.current)
- playlist.current = i;
- else if (i == playlist.current)
- playlist.current = ri;
- swapOrder(i, ri);
- }
-
-}
-
-int setPlaylistRandomStatus(int fd, int status)
-{
- int statusWas = playlist.random;
-
- if (status != 0 && status != 1) {
- commandError(fd, ACK_ERROR_ARG, "\"%i\" is not 0 or 1", status);
- return -1;
- }
-
- playlist.random = status;
-
- if (status != statusWas) {
- if (playlist.random) {
- /*if(playlist_state==PLAYLIST_STATE_PLAY) {
- randomizeOrder(playlist.current+1,
- playlist.length-1);
- }
- else */ randomizeOrder(0, playlist.length - 1);
- if (playlist.current >= 0 &&
- playlist.current < playlist.length) {
- swapOrder(playlist.current, 0);
- playlist.current = 0;
- }
- } else
- orderPlaylist();
- }
-
- return 0;
-}
-
-int previousSongInPlaylist(int fd)
-{
- static time_t lastTime;
- time_t diff = time(NULL) - lastTime;
-
- lastTime += diff;
-
- if (playlist_state != PLAYLIST_STATE_PLAY)
- return 0;
-
- syncPlaylistWithQueue(0);
-
- if (diff && getPlayerElapsedTime() > PLAYLIST_PREV_UNLESS_ELAPSED) {
- return playPlaylistOrderNumber(fd, playlist.current);
- } else {
- if (playlist.current > 0) {
- return playPlaylistOrderNumber(fd,
- playlist.current - 1);
- } else if (playlist.repeat) {
- return playPlaylistOrderNumber(fd, playlist.length - 1);
- } else {
- return playPlaylistOrderNumber(fd, playlist.current);
- }
- }
-
- return 0;
-}
-
-int shufflePlaylist(int fd)
-{
- int i;
- int ri;
-
- if (playlist.length > 1) {
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- /* put current playing song first */
- swapSongs(0, playlist.order[playlist.current]);
- if (playlist.random) {
- int j;
- for (j = 0; 0 != playlist.order[j]; j++) ;
- playlist.current = j;
- } else
- playlist.current = 0;
- i = 1;
- } else {
- i = 0;
- playlist.current = -1;
- }
- /* shuffle the rest of the list */
- for (; i < playlist.length; i++) {
- ri = random() % (playlist.length - 1) + 1;
- swapSongs(i, ri);
- }
-
- incrPlaylistVersion();
- }
-
- return 0;
-}
-
-int deletePlaylist(int fd, char *utf8file)
-{
- char *file = utf8ToFsCharset(utf8file);
- char *rfile = xmalloc(strlen(file) + strlen(".") +
- strlen(PLAYLIST_FILE_SUFFIX) + 1);
- char *actualFile;
-
- strcpy(rfile, file);
- strcat(rfile, ".");
- strcat(rfile, PLAYLIST_FILE_SUFFIX);
-
- if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile))
- free(rfile);
- else {
- free(rfile);
- commandError(fd, ACK_ERROR_NO_EXIST,
- "playlist \"%s\" not found", utf8file);
- return -1;
- }
-
- if (unlink(actualFile) < 0) {
- commandError(fd, ACK_ERROR_SYSTEM,
- "problems deleting file");
- return -1;
- }
-
- return 0;
-}
-
-int savePlaylist(int fd, char *utf8file)
-{
- StoredPlaylist *sp = newStoredPlaylist(utf8file, fd, 0);
- if (!sp)
- return -1;
-
- appendPlaylistToStoredPlaylist(sp, &playlist);
- if (writeStoredPlaylist(sp) != 0) {
- freeStoredPlaylist(sp);
- return -1;
- }
-
- freeStoredPlaylist(sp);
- return 0;
-}
-
-int getPlaylistCurrentSong(void)
-{
- if (playlist.current >= 0 && playlist.current < playlist.length) {
- return playlist.order[playlist.current];
- }
-
- return -1;
-}
-
-unsigned long getPlaylistVersion(void)
-{
- return playlist.version;
-}
-
-int getPlaylistLength(void)
-{
- return playlist.length;
-}
-
-int seekSongInPlaylist(int fd, int song, float time)
-{
- int i = song;
-
- if (song < 0 || song >= playlist.length) {
- commandError(fd, ACK_ERROR_NO_EXIST,
- "song doesn't exist: \"%i\"", song);
- return -1;
- }
-
- if (playlist.random)
- for (i = 0; song != playlist.order[i]; i++) ;
-
- clearPlayerError();
- playlist_stopOnError = 1;
- playlist_errorCount = 0;
-
- if (playlist_state == PLAYLIST_STATE_PLAY) {
- if (playlist.queued >= 0) {
- lockPlaylistInteraction();
- clearPlayerQueue();
- unlockPlaylistInteraction();
- }
- } else if (playPlaylistOrderNumber(fd, i) < 0)
- return -1;
-
- if (playlist.current != i) {
- if (playPlaylistOrderNumber(fd, i) < 0)
- return -1;
- }
-
- return playerSeek(fd, playlist.songs[playlist.order[i]], time);
-}
-
-int seekSongInPlaylistById(int fd, int id, float time)
-{
- checkSongId(id);
-
- return seekSongInPlaylist(fd, playlist.idToPosition[id], time);
-}
-
-int getPlaylistSongId(int song)
-{
- return playlist.positionToId[song];
-}
-
-int PlaylistInfo(int fd, char *utf8file, int detail)
-{
- ListNode *node;
- StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd);
- if (sp == NULL)
- return -1;
-
- node = sp->list->firstNode;
- while (node != NULL) {
- char *temp = node->data;
- int wrote = 0;
-
- if (detail) {
- Song *song = getSongFromDB(temp);
- if (song) {
- printSongInfo(fd, song);
- wrote = 1;
- }
- }
-
- if (!wrote) {
- fdprintf(fd, SONG_FILE "%s\n", temp);
- }
-
- node = node->nextNode;
- }
-
- freeStoredPlaylist(sp);
- return 0;
-}
-
-int loadPlaylist(int fd, char *utf8file)
-{
- ListNode *node;
- StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd);
- if (sp == NULL)
- return -1;
-
- node = sp->list->firstNode;
- while (node != NULL) {
- char *temp = node->data;
- if ((addToPlaylist(STDERR_FILENO, temp, 0)) < 0) {
- /* for windows compatibility, convert slashes */
- char *temp2 = xstrdup(temp);
- char *p = temp2;
- while (*p) {
- if (*p == '\\')
- *p = '/';
- p++;
- }
- if ((addToPlaylist(STDERR_FILENO, temp2, 0)) < 0) {
- commandError(fd, ACK_ERROR_PLAYLIST_LOAD,
- "can't add file \"%s\"", temp2);
- }
- free(temp2);
- }
-
- node = node->nextNode;
- }
-
- freeStoredPlaylist(sp);
- return 0;
-}
-
-void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items)
-{
- int i;
- char **originalNeedles = xmalloc(numItems * sizeof(char *));
-
- for (i = 0; i < numItems; i++) {
- originalNeedles[i] = items[i].needle;
- items[i].needle = strDupToUpper(originalNeedles[i]);
- }
-
- for (i = 0; i < playlist.length; i++) {
- if (strstrSearchTags(playlist.songs[i], numItems, items))
- printPlaylistSongInfo(fd, i);
- }
-
- for (i = 0; i < numItems; i++) {
- free(items[i].needle);
- items[i].needle = originalNeedles[i];
- }
-
- free(originalNeedles);
-}
-
-void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items)
-{
- int i;
-
- for (i = 0; i < playlist.length; i++) {
- if (tagItemsFoundAndMatches(playlist.songs[i], numItems, items))
- printPlaylistSongInfo(fd, i);
- }
-}