2
* Copyright (C) 2003-2013 The Music Player Daemon Project
3
* http://www.musicpd.org
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
* Functions for controlling playback on the playlist level.
26
#include "Playlist.hxx"
27
#include "PlaylistError.hxx"
28
#include "PlayerControl.hxx"
33
playlist::Stop(PlayerControl &pc)
40
FormatDebug(playlist_domain, "stop");
46
/* shuffle the playlist, so the next playback will
47
result in a new random order */
49
unsigned current_position = queue.OrderToPosition(current);
53
/* make sure that "current" stays valid, and the next
54
"play" command plays the same song again */
55
current = queue.PositionToOrder(current_position);
60
playlist::PlayPosition(PlayerControl &pc, int song)
66
/* play any song ("current" song, or the first song */
69
return PlaylistResult::SUCCESS;
72
/* already playing: unpause playback, just in
73
case it was paused, and return */
75
return PlaylistResult::SUCCESS;
78
/* select a song: "current" song, or the first one */
82
} else if (!queue.IsValidPosition(song))
83
return PlaylistResult::BAD_RANGE;
87
/* "i" is currently the song position (which
88
would be equal to the order number in
89
no-random mode); convert it to a order
90
number, because random mode is enabled */
91
i = queue.PositionToOrder(song);
96
/* swap the new song with the previous "current" one,
97
so playback continues as planned */
98
queue.SwapOrders(i, current);
102
stop_on_error = false;
106
return PlaylistResult::SUCCESS;
110
playlist::PlayId(PlayerControl &pc, int id)
113
return PlayPosition(pc, id);
115
int song = queue.IdToPosition(id);
117
return PlaylistResult::NO_SUCH_SONG;
119
return PlayPosition(pc, song);
123
playlist::PlayNext(PlayerControl &pc)
128
assert(!queue.IsEmpty());
129
assert(queue.IsValidOrder(current));
131
const int old_current = current;
132
stop_on_error = false;
134
/* determine the next song from the queue's order list */
136
const int next_order = queue.GetNextOrder(current);
137
if (next_order < 0) {
138
/* no song after this one: stop playback */
141
/* reset "current song" */
146
if (next_order == 0 && queue.random) {
147
/* The queue told us that the next song is the first
148
song. This means we are in repeat mode. Shuffle
149
the queue order, so this time, the user hears the
150
songs in a different than before */
151
assert(queue.repeat);
153
queue.ShuffleOrder();
155
/* note that current and queued are
156
now invalid, but playlist_play_order() will
157
discard them anyway */
160
PlayOrder(pc, next_order);
163
/* Consume mode removes each played songs. */
165
DeleteOrder(pc, old_current);
169
playlist::PlayPrevious(PlayerControl &pc)
174
assert(!queue.IsEmpty());
178
/* play the preceding song */
180
} else if (queue.repeat) {
181
/* play the last song in "repeat" mode */
182
order = queue.GetLength() - 1;
184
/* re-start playing the current song if it's
189
PlayOrder(pc, order);
193
playlist::SeekSongPosition(PlayerControl &pc, unsigned song, float seek_time)
195
if (!queue.IsValidPosition(song))
196
return PlaylistResult::BAD_RANGE;
198
const Song *queued_song = GetQueuedSong();
200
unsigned i = queue.random
201
? queue.PositionToOrder(song)
205
stop_on_error = true;
208
if (!playing || (unsigned)current != i) {
209
/* seeking is not within the current song - prepare
215
queued_song = nullptr;
218
Song *the_song = queue.GetOrder(i).DupDetached();
219
if (!pc.Seek(the_song, seek_time)) {
220
UpdateQueuedSong(pc, queued_song);
222
return PlaylistResult::NOT_PLAYING;
226
UpdateQueuedSong(pc, nullptr);
228
return PlaylistResult::SUCCESS;
232
playlist::SeekSongId(PlayerControl &pc, unsigned id, float seek_time)
234
int song = queue.IdToPosition(id);
236
return PlaylistResult::NO_SUCH_SONG;
238
return SeekSongPosition(pc, song, seek_time);
242
playlist::SeekCurrent(PlayerControl &pc, float seek_time, bool relative)
245
return PlaylistResult::NOT_PLAYING;
248
const auto status = pc.GetStatus();
250
if (status.state != PlayerState::PLAY &&
251
status.state != PlayerState::PAUSE)
252
return PlaylistResult::NOT_PLAYING;
254
seek_time += (int)status.elapsed_time;
260
return SeekSongPosition(pc, current, seek_time);