17
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
#include "playlist_internal.h"
21
22
#include "playlist_save.h"
22
23
#include "player_control.h"
91
89
g_debug("queue song %i:\"%s\"", playlist->queued, uri);
92
pc_enqueue_song(song);
98
* Check if the player thread has already started playing the "queued"
96
* Called if the player thread has started playing the "queued" song.
101
static void syncPlaylistWithQueue(struct playlist *playlist)
99
playlist_song_started(struct playlist *playlist)
103
if (pc.next_song == NULL && playlist->queued != -1) {
104
/* queued song has started: copy queued to current,
105
and notify the clients */
107
int current = playlist->current;
108
playlist->current = playlist->queued;
109
playlist->queued = -1;
111
if(playlist->queue.consume)
112
deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current));
114
idle_add(IDLE_PLAYER);
101
assert(pc.next_song == NULL);
102
assert(playlist->queued >= -1);
104
/* queued song has started: copy queued to current,
105
and notify the clients */
107
int current = playlist->current;
108
playlist->current = playlist->queued;
109
playlist->queued = -1;
111
/* Pause if we are in single mode. */
112
if(playlist->queue.single && !playlist->queue.repeat) {
116
if(playlist->queue.consume)
117
playlist_delete(playlist, queue_order_to_position(&playlist->queue, current));
119
idle_add(IDLE_PLAYER);
118
122
const struct song *
193
197
g_debug("play %i:\"%s\"", orderNum, uri);
197
201
playlist->current = orderNum;
201
playPlaylistIfPlayerStopped(struct playlist *playlist);
205
playlist_resume_playback(struct playlist *playlist);
204
208
* This is the "PLAYLIST" event handler. It is invoked by the player
205
209
* thread whenever it requests a new queued song, or when it exits.
207
void syncPlayerAndPlaylist(struct playlist *playlist)
212
playlist_sync(struct playlist *playlist)
209
214
if (!playlist->playing)
210
215
/* this event has reached us out of sync: we aren't
211
216
playing anymore; ignore the event */
214
if (getPlayerState() == PLAYER_STATE_STOP)
220
enum player_state pc_state = pc_get_state();
221
const struct song *pc_next_song = pc.next_song;
224
if (pc_state == PLAYER_STATE_STOP)
215
225
/* the player thread has stopped: check if playback
216
226
should be restarted with the next song. That can
217
227
happen if the playlist isn't filling the queue fast
219
playPlaylistIfPlayerStopped(playlist);
229
playlist_resume_playback(playlist);
221
231
/* check if the player thread has already started
222
232
playing the queued song */
223
syncPlaylistWithQueue(playlist);
233
if (pc_next_song == NULL && playlist->queued != -1)
234
playlist_song_started(playlist);
225
236
/* make sure the queued song is always set (if
227
if (pc.next_song == NULL)
238
if (pc.next_song == NULL && playlist->queued < 0)
228
239
playlist_update_queued_song(playlist, NULL);
234
245
* decide whether to re-start playback
237
playPlaylistIfPlayerStopped(struct playlist *playlist)
248
playlist_resume_playback(struct playlist *playlist)
239
250
enum player_error error;
241
252
assert(playlist->playing);
242
assert(getPlayerState() == PLAYER_STATE_STOP);
253
assert(pc_get_state() == PLAYER_STATE_STOP);
244
error = getPlayerError();
255
error = pc_get_error();
245
256
if (error == PLAYER_ERROR_NOERROR)
246
257
playlist->error_count = 0;
252
263
playlist->error_count >= queue_length(&playlist->queue))
253
264
/* too many errors, or critical error: stop
255
stopPlaylist(playlist);
266
playlist_stop(playlist);
257
268
/* continue playback at the next song */
258
nextSongInPlaylist(playlist);
269
playlist_next(playlist);
262
getPlaylistRepeatStatus(const struct playlist *playlist)
273
playlist_get_repeat(const struct playlist *playlist)
264
275
return playlist->queue.repeat;
268
getPlaylistRandomStatus(const struct playlist *playlist)
279
playlist_get_random(const struct playlist *playlist)
270
281
return playlist->queue.random;
274
getPlaylistSingleStatus(const struct playlist *playlist)
285
playlist_get_single(const struct playlist *playlist)
276
287
return playlist->queue.single;
280
getPlaylistConsumeStatus(const struct playlist *playlist)
291
playlist_get_consume(const struct playlist *playlist)
282
293
return playlist->queue.consume;
285
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
297
playlist_set_repeat(struct playlist *playlist, bool status)
287
299
if (status == playlist->queue.repeat)
297
309
idle_add(IDLE_OPTIONS);
300
static void orderPlaylist(struct playlist *playlist)
313
playlist_order(struct playlist *playlist)
302
315
if (playlist->current >= 0)
303
316
/* update playlist.current, order==position now */
307
320
queue_restore_order(&playlist->queue);
310
void setPlaylistSingleStatus(struct playlist *playlist, bool status)
324
playlist_set_single(struct playlist *playlist, bool status)
312
326
if (status == playlist->queue.single)
367
383
playlist->current = -1;
369
orderPlaylist(playlist);
385
playlist_order(playlist);
371
387
playlist_update_queued_song(playlist, queued);
373
389
idle_add(IDLE_OPTIONS);
376
int getPlaylistCurrentSong(const struct playlist *playlist)
393
playlist_get_current_song(const struct playlist *playlist)
378
395
if (playlist->current >= 0)
379
396
return queue_order_to_position(&playlist->queue,
385
int getPlaylistNextSong(const struct playlist *playlist)
403
playlist_get_next_song(const struct playlist *playlist)
387
405
if (playlist->current >= 0)
389
if (playlist->queue.single == 1)
391
if (playlist->queue.repeat == 1)
392
return queue_order_to_position(&playlist->queue,
397
if (playlist->current + 1 < (int)queue_length(&playlist->queue))
407
if (playlist->queue.single == 1 && playlist->queue.repeat == 1)
408
return queue_order_to_position(&playlist->queue,
410
else if (playlist->current + 1 < (int)queue_length(&playlist->queue))
398
411
return queue_order_to_position(&playlist->queue,
399
412
playlist->current + 1);
400
413
else if (playlist->queue.repeat == 1)
408
getPlaylistVersion(const struct playlist *playlist)
421
playlist_get_version(const struct playlist *playlist)
410
423
return playlist->queue.version;
414
getPlaylistLength(const struct playlist *playlist)
427
playlist_get_length(const struct playlist *playlist)
416
429
return queue_length(&playlist->queue);
420
getPlaylistSongId(const struct playlist *playlist, unsigned song)
433
playlist_get_song_id(const struct playlist *playlist, unsigned song)
422
435
return queue_position_to_id(&playlist->queue, song);