Commit 471c37be authored by Max Kellermann's avatar Max Kellermann

queue/PlaylistEdit: convert start/end parameters to RangeArg

parent 157ddcba
......@@ -27,6 +27,7 @@
#include "mixer/Listener.hxx"
#include "player/Control.hxx"
#include "player/Listener.hxx"
#include "protocol/RangeArg.hxx"
#include "ReplayGainMode.hxx"
#include "SingleMode.hxx"
#include "Chrono.hxx"
......@@ -38,6 +39,7 @@
#include <memory>
struct Instance;
struct RangeArg;
class MultipleOutputs;
class SongLoader;
class ClientListener;
......@@ -133,20 +135,20 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
* @param start the position of the first song to delete
* @param end the position after the last song to delete
*/
void DeleteRange(unsigned start, unsigned end) {
playlist.DeleteRange(pc, start, end);
void DeleteRange(RangeArg range) {
playlist.DeleteRange(pc, range);
}
void StaleSong(const char *uri) noexcept {
playlist.StaleSong(pc, uri);
}
void Shuffle(unsigned start, unsigned end) noexcept {
playlist.Shuffle(pc, start, end);
void Shuffle(RangeArg range) {
playlist.Shuffle(pc, range);
}
void MoveRange(unsigned start, unsigned end, int to) {
playlist.MoveRange(pc, start, end, to);
void MoveRange(RangeArg range, int to) {
playlist.MoveRange(pc, range, to);
}
void MoveId(unsigned id, int to) {
......@@ -161,10 +163,8 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
playlist.SwapIds(pc, id1, id2);
}
void SetPriorityRange(unsigned start_position, unsigned end_position,
uint8_t priority) {
playlist.SetPriorityRange(pc, start_position, end_position,
priority);
void SetPriorityRange(RangeArg position_range, uint8_t priority) {
playlist.SetPriorityRange(pc, position_range, priority);
}
void SetPriorityId(unsigned song_id, uint8_t priority) {
......
......@@ -22,6 +22,7 @@
#include "PlaylistError.hxx"
#include "queue/Playlist.hxx"
#include "queue/QueuePrint.hxx"
#include "protocol/RangeArg.hxx"
#define SONG_FILE "file: "
#define SONG_TIME "Time: "
......@@ -35,20 +36,17 @@ playlist_print_uris(Response &r, const playlist &playlist)
}
void
playlist_print_info(Response &r, const playlist &playlist,
unsigned start, unsigned end)
playlist_print_info(Response &r, const playlist &playlist, RangeArg range)
{
const Queue &queue = playlist.queue;
if (end > queue.GetLength())
/* correct the "end" offset */
end = queue.GetLength();
if (start > end)
/* an invalid "start" offset is fatal */
if (!range.CheckClip(queue.GetLength()))
throw PlaylistError::BadRange();
queue_print_info(r, queue, start, end);
if (range.IsEmpty())
return;
queue_print_info(r, queue, range.start, range.end);
}
void
......@@ -62,7 +60,7 @@ playlist_print_id(Response &r, const playlist &playlist,
/* no such song */
throw PlaylistError::NoSuchSong();
playlist_print_info(r, playlist, position, position + 1);
playlist_print_info(r, playlist, {unsigned(position), position + 1U});
}
bool
......@@ -87,18 +85,24 @@ playlist_print_find(Response &r, const playlist &playlist,
void
playlist_print_changes_info(Response &r, const playlist &playlist,
uint32_t version,
unsigned start, unsigned end)
RangeArg range)
{
queue_print_changes_info(r, playlist.queue, version,
start, end);
const Queue &queue = playlist.queue;
range.ClipRelaxed(queue.GetLength());
queue_print_changes_info(r, queue, version,
range.start, range.end);
}
void
playlist_print_changes_position(Response &r,
const playlist &playlist,
uint32_t version,
unsigned start, unsigned end)
RangeArg range)
{
const Queue &queue = playlist.queue;
range.ClipRelaxed(queue.GetLength());
queue_print_changes_position(r, playlist.queue, version,
start, end);
range.start, range.end);
}
......@@ -23,6 +23,7 @@
#include <cstdint>
struct playlist;
struct RangeArg;
class SongFilter;
class Response;
......@@ -41,8 +42,7 @@ playlist_print_uris(Response &r, const playlist &playlist);
* Throws #PlaylistError if the range is invalid.
*/
void
playlist_print_info(Response &r, const playlist &playlist,
unsigned start, unsigned end);
playlist_print_info(Response &r, const playlist &playlist, RangeArg range);
/**
* Sends the song with the specified id to the client.
......@@ -73,7 +73,7 @@ playlist_print_find(Response &r, const playlist &playlist,
void
playlist_print_changes_info(Response &r, const playlist &playlist,
uint32_t version,
unsigned start, unsigned end);
RangeArg range);
/**
* Print changes since the specified playlist version, position only.
......@@ -82,6 +82,6 @@ void
playlist_print_changes_position(Response &r,
const playlist &playlist,
uint32_t version,
unsigned start, unsigned end);
RangeArg range);
#endif
......@@ -182,7 +182,7 @@ CommandResult
handle_delete(Client &client, Request args, [[maybe_unused]] Response &r)
{
RangeArg range = args.ParseRange(0);
client.GetPartition().DeleteRange(range.start, range.end);
client.GetPartition().DeleteRange(range);
return CommandResult::OK;
}
......@@ -205,7 +205,7 @@ CommandResult
handle_shuffle([[maybe_unused]] Client &client, Request args, [[maybe_unused]] Response &r)
{
RangeArg range = args.ParseOptional(0, RangeArg::All());
client.GetPartition().Shuffle(range.start, range.end);
client.GetPartition().Shuffle(range);
return CommandResult::OK;
}
......@@ -221,8 +221,7 @@ handle_plchanges(Client &client, Request args, Response &r)
{
uint32_t version = ParseCommandArgU32(args.front());
RangeArg range = args.ParseOptional(1, RangeArg::All());
playlist_print_changes_info(r, client.GetPlaylist(), version,
range.start, range.end);
playlist_print_changes_info(r, client.GetPlaylist(), version, range);
return CommandResult::OK;
}
......@@ -232,7 +231,7 @@ handle_plchangesposid(Client &client, Request args, Response &r)
uint32_t version = ParseCommandArgU32(args.front());
RangeArg range = args.ParseOptional(1, RangeArg::All());
playlist_print_changes_position(r, client.GetPlaylist(), version,
range.start, range.end);
range);
return CommandResult::OK;
}
......@@ -241,8 +240,7 @@ handle_playlistinfo(Client &client, Request args, Response &r)
{
RangeArg range = args.ParseOptional(0, RangeArg::All());
playlist_print_info(r, client.GetPlaylist(),
range.start, range.end);
playlist_print_info(r, client.GetPlaylist(), range);
return CommandResult::OK;
}
......@@ -253,8 +251,7 @@ handle_playlistid(Client &client, Request args, Response &r)
unsigned id = args.ParseUnsigned(0);
playlist_print_id(r, client.GetPlaylist(), id);
} else {
playlist_print_info(r, client.GetPlaylist(),
0, std::numeric_limits<unsigned>::max());
playlist_print_info(r, client.GetPlaylist(), RangeArg::All());
}
return CommandResult::OK;
......@@ -300,7 +297,7 @@ handle_prio(Client &client, Request args, [[maybe_unused]] Response &r)
for (const char *i : args) {
RangeArg range = ParseCommandArgRange(i);
partition.SetPriorityRange(range.start, range.end, priority);
partition.SetPriorityRange(range, priority);
}
return CommandResult::OK;
......@@ -332,7 +329,7 @@ handle_move(Client &client, Request args, [[maybe_unused]] Response &r)
}
int to = args.ParseInt(1);
client.GetPartition().MoveRange(range.start, range.end, to);
client.GetPartition().MoveRange(range, to);
return CommandResult::OK;
}
......
......@@ -26,6 +26,7 @@
enum TagType : uint8_t;
struct Tag;
struct RangeArg;
class PlayerControl;
class DetachedSong;
class Database;
......@@ -240,7 +241,7 @@ public:
* @param start the position of the first song to delete
* @param end the position after the last song to delete
*/
void DeleteRange(PlayerControl &pc, unsigned start, unsigned end);
void DeleteRange(PlayerControl &pc, RangeArg range);
/**
* Mark the given song as "stale", i.e. as not being available
......@@ -250,10 +251,9 @@ public:
*/
void StaleSong(PlayerControl &pc, const char *uri) noexcept;
void Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept;
void Shuffle(PlayerControl &pc, RangeArg range);
void MoveRange(PlayerControl &pc, unsigned start,
unsigned end, int to);
void MoveRange(PlayerControl &pc, RangeArg range, int to);
void MoveId(PlayerControl &pc, unsigned id, int to);
......@@ -262,7 +262,7 @@ public:
void SwapIds(PlayerControl &pc, unsigned id1, unsigned id2);
void SetPriorityRange(PlayerControl &pc,
unsigned start_position, unsigned end_position,
RangeArg position_range,
uint8_t priority);
void SetPriorityId(PlayerControl &pc,
......
......@@ -27,6 +27,7 @@
#include "Listener.hxx"
#include "PlaylistError.hxx"
#include "player/Control.hxx"
#include "protocol/RangeArg.hxx"
#include "song/DetachedSong.hxx"
#include "SongLoader.hxx"
......@@ -168,16 +169,13 @@ playlist::SwapIds(PlayerControl &pc, unsigned id1, unsigned id2)
void
playlist::SetPriorityRange(PlayerControl &pc,
unsigned start, unsigned end,
RangeArg range,
uint8_t priority)
{
if (start >= GetLength())
if (!range.CheckClip(GetLength()))
throw PlaylistError::BadRange();
if (end > GetLength())
end = GetLength();
if (start >= end)
if (range.IsEmpty())
return;
/* remember "current" and "queued" */
......@@ -187,7 +185,7 @@ playlist::SetPriorityRange(PlayerControl &pc,
/* apply the priority changes */
queue.SetPriorityRange(start, end, priority, current);
queue.SetPriorityRange(range.start, range.end, priority, current);
/* restore "current" and choose a new "queued" */
......@@ -206,7 +204,7 @@ playlist::SetPriorityId(PlayerControl &pc,
if (song_position < 0)
throw PlaylistError::NoSuchSong();
SetPriorityRange(pc, song_position, song_position + 1, priority);
SetPriorityRange(pc, {unsigned(song_position), song_position + 1U}, priority);
}
void
......@@ -272,22 +270,19 @@ playlist::DeletePosition(PlayerControl &pc, unsigned song)
}
void
playlist::DeleteRange(PlayerControl &pc, unsigned start, unsigned end)
playlist::DeleteRange(PlayerControl &pc, RangeArg range)
{
if (start >= queue.GetLength())
if (!range.CheckClip(GetLength()))
throw PlaylistError::BadRange();
if (end > queue.GetLength())
end = queue.GetLength();
if (start >= end)
if (range.IsEmpty())
return;
const DetachedSong *queued_song = GetQueuedSong();
do {
DeleteInternal(pc, --end, &queued_song);
} while (end != start);
DeleteInternal(pc, --range.end, &queued_song);
} while (range.end != range.start);
UpdateQueuedSong(pc, queued_song);
OnModified();
......@@ -320,17 +315,17 @@ playlist::StaleSong(PlayerControl &pc, const char *uri) noexcept
}
void
playlist::MoveRange(PlayerControl &pc,
unsigned start, unsigned end, int to)
playlist::MoveRange(PlayerControl &pc, RangeArg range, int to)
{
if (!queue.IsValidPosition(start) || !queue.IsValidPosition(end - 1))
if (!queue.IsValidPosition(range.start) ||
!queue.IsValidPosition(range.end - 1))
throw PlaylistError::BadRange();
if ((to >= 0 && to + end - start - 1 >= GetLength()) ||
if ((to >= 0 && to + range.Count() - 1 >= GetLength()) ||
(to < 0 && unsigned(std::abs(to)) > GetLength()))
throw PlaylistError::BadRange();
if ((int)start == to)
if ((int)range.start == to)
/* nothing happens */
return;
......@@ -347,26 +342,26 @@ playlist::MoveRange(PlayerControl &pc,
because there is no current song */
throw PlaylistError::BadRange();
if (start <= (unsigned)currentSong && (unsigned)currentSong < end)
if (range.Contains(currentSong))
/* no-op, can't be moved to offset of itself */
return;
to = (currentSong + std::abs(to)) % GetLength();
if (start < (unsigned)to)
to -= end - start;
if (range.start < (unsigned)to)
to -= range.Count();
}
queue.MoveRange(start, end, to);
queue.MoveRange(range.start, range.end, to);
if (!queue.random && current >= 0) {
/* update current */
if (start <= unsigned(current) && unsigned(current) < end)
current += unsigned(to) - start;
else if (unsigned(current) >= end &&
if (range.Contains(current))
current += unsigned(to) - range.start;
else if (unsigned(current) >= range.end &&
unsigned(current) <= unsigned(to))
current -= end - start;
current -= range.Count();
else if (unsigned(current) >= unsigned(to) &&
unsigned(current) < start)
current += end - start;
unsigned(current) < range.start)
current += range.Count();
}
UpdateQueuedSong(pc, queued_song);
......@@ -380,17 +375,16 @@ playlist::MoveId(PlayerControl &pc, unsigned id1, int to)
if (song < 0)
throw PlaylistError::NoSuchSong();
MoveRange(pc, song, song + 1, to);
MoveRange(pc, RangeArg::Single(song), to);
}
void
playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept
playlist::Shuffle(PlayerControl &pc, RangeArg range)
{
if (end > GetLength())
/* correct the "end" offset */
end = GetLength();
if (!range.CheckClip(GetLength()))
throw PlaylistError::BadRange();
if (start + 1 >= end)
if (range.HasAtLeast(2))
/* needs at least two entries. */
return;
......@@ -398,17 +392,17 @@ playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept
if (playing && current >= 0) {
unsigned current_position = queue.OrderToPosition(current);
if (current_position >= start && current_position < end) {
if (range.Contains(current_position)) {
/* put current playing song first */
queue.SwapPositions(start, current_position);
queue.SwapPositions(range.start, current_position);
if (queue.random) {
current = queue.PositionToOrder(start);
current = queue.PositionToOrder(range.start);
} else
current = start;
current = range.start;
/* start shuffle after the current song */
start++;
range.start++;
}
} else {
/* no playback currently: reset current */
......@@ -416,7 +410,7 @@ playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept
current = -1;
}
queue.ShuffleRange(start, end);
queue.ShuffleRange(range.start, range.end);
UpdateQueuedSong(pc, queued_song);
OnModified();
......
......@@ -76,12 +76,7 @@ queue_print_changes_info(Response &r, const Queue &queue,
unsigned start, unsigned end)
{
assert(start <= end);
if (start >= queue.GetLength())
return;
if (end > queue.GetLength())
end = queue.GetLength();
assert(end <= queue.GetLength());
for (unsigned i = start; i < end; i++)
if (queue.IsNewerAtPosition(i, version))
......@@ -94,12 +89,7 @@ queue_print_changes_position(Response &r, const Queue &queue,
unsigned start, unsigned end)
{
assert(start <= end);
if (start >= queue.GetLength())
return;
if (end > queue.GetLength())
end = queue.GetLength();
assert(end <= queue.GetLength());
for (unsigned i = start; i < end; i++)
if (queue.IsNewerAtPosition(i, version))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment