diff --git a/src/Partition.hxx b/src/Partition.hxx index c6255ce4a..5bf6b7243 100644 --- a/src/Partition.hxx +++ b/src/Partition.hxx @@ -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 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) { diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx index b023af89a..45dfe12d2 100644 --- a/src/PlaylistPrint.cxx +++ b/src/PlaylistPrint.cxx @@ -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); } diff --git a/src/PlaylistPrint.hxx b/src/PlaylistPrint.hxx index 001761506..d970289ea 100644 --- a/src/PlaylistPrint.hxx +++ b/src/PlaylistPrint.hxx @@ -23,6 +23,7 @@ #include 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 diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx index ba8c5a423..c0161779e 100644 --- a/src/command/QueueCommands.cxx +++ b/src/command/QueueCommands.cxx @@ -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::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; } diff --git a/src/queue/Playlist.hxx b/src/queue/Playlist.hxx index e30dc8854..a04685a2d 100644 --- a/src/queue/Playlist.hxx +++ b/src/queue/Playlist.hxx @@ -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, diff --git a/src/queue/PlaylistEdit.cxx b/src/queue/PlaylistEdit.cxx index 3a98ed39c..1002d73e6 100644 --- a/src/queue/PlaylistEdit.cxx +++ b/src/queue/PlaylistEdit.cxx @@ -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(); diff --git a/src/queue/QueuePrint.cxx b/src/queue/QueuePrint.cxx index 55728e49b..3f24de785 100644 --- a/src/queue/QueuePrint.cxx +++ b/src/queue/QueuePrint.cxx @@ -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))