queue/PlaylistEdit: convert start/end parameters to RangeArg

This commit is contained in:
Max Kellermann 2021-02-15 19:25:36 +01:00
parent 157ddcbab1
commit 471c37be59
7 changed files with 85 additions and 100 deletions

View File

@ -27,6 +27,7 @@
#include "mixer/Listener.hxx" #include "mixer/Listener.hxx"
#include "player/Control.hxx" #include "player/Control.hxx"
#include "player/Listener.hxx" #include "player/Listener.hxx"
#include "protocol/RangeArg.hxx"
#include "ReplayGainMode.hxx" #include "ReplayGainMode.hxx"
#include "SingleMode.hxx" #include "SingleMode.hxx"
#include "Chrono.hxx" #include "Chrono.hxx"
@ -38,6 +39,7 @@
#include <memory> #include <memory>
struct Instance; struct Instance;
struct RangeArg;
class MultipleOutputs; class MultipleOutputs;
class SongLoader; class SongLoader;
class ClientListener; class ClientListener;
@ -133,20 +135,20 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
* @param start the position of the first song to delete * @param start the position of the first song to delete
* @param end the position after the last song to delete * @param end the position after the last song to delete
*/ */
void DeleteRange(unsigned start, unsigned end) { void DeleteRange(RangeArg range) {
playlist.DeleteRange(pc, start, end); playlist.DeleteRange(pc, range);
} }
void StaleSong(const char *uri) noexcept { void StaleSong(const char *uri) noexcept {
playlist.StaleSong(pc, uri); playlist.StaleSong(pc, uri);
} }
void Shuffle(unsigned start, unsigned end) noexcept { void Shuffle(RangeArg range) {
playlist.Shuffle(pc, start, end); playlist.Shuffle(pc, range);
} }
void MoveRange(unsigned start, unsigned end, int to) { void MoveRange(RangeArg range, int to) {
playlist.MoveRange(pc, start, end, to); playlist.MoveRange(pc, range, to);
} }
void MoveId(unsigned id, int to) { void MoveId(unsigned id, int to) {
@ -161,10 +163,8 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
playlist.SwapIds(pc, id1, id2); playlist.SwapIds(pc, id1, id2);
} }
void SetPriorityRange(unsigned start_position, unsigned end_position, void SetPriorityRange(RangeArg position_range, uint8_t priority) {
uint8_t priority) { playlist.SetPriorityRange(pc, position_range, priority);
playlist.SetPriorityRange(pc, start_position, end_position,
priority);
} }
void SetPriorityId(unsigned song_id, uint8_t priority) { void SetPriorityId(unsigned song_id, uint8_t priority) {

View File

@ -22,6 +22,7 @@
#include "PlaylistError.hxx" #include "PlaylistError.hxx"
#include "queue/Playlist.hxx" #include "queue/Playlist.hxx"
#include "queue/QueuePrint.hxx" #include "queue/QueuePrint.hxx"
#include "protocol/RangeArg.hxx"
#define SONG_FILE "file: " #define SONG_FILE "file: "
#define SONG_TIME "Time: " #define SONG_TIME "Time: "
@ -35,20 +36,17 @@ playlist_print_uris(Response &r, const playlist &playlist)
} }
void void
playlist_print_info(Response &r, const playlist &playlist, playlist_print_info(Response &r, const playlist &playlist, RangeArg range)
unsigned start, unsigned end)
{ {
const Queue &queue = playlist.queue; const Queue &queue = playlist.queue;
if (end > queue.GetLength()) if (!range.CheckClip(queue.GetLength()))
/* correct the "end" offset */
end = queue.GetLength();
if (start > end)
/* an invalid "start" offset is fatal */
throw PlaylistError::BadRange(); throw PlaylistError::BadRange();
queue_print_info(r, queue, start, end); if (range.IsEmpty())
return;
queue_print_info(r, queue, range.start, range.end);
} }
void void
@ -62,7 +60,7 @@ playlist_print_id(Response &r, const playlist &playlist,
/* no such song */ /* no such song */
throw PlaylistError::NoSuchSong(); throw PlaylistError::NoSuchSong();
playlist_print_info(r, playlist, position, position + 1); playlist_print_info(r, playlist, {unsigned(position), position + 1U});
} }
bool bool
@ -87,18 +85,24 @@ playlist_print_find(Response &r, const playlist &playlist,
void void
playlist_print_changes_info(Response &r, const playlist &playlist, playlist_print_changes_info(Response &r, const playlist &playlist,
uint32_t version, uint32_t version,
unsigned start, unsigned end) RangeArg range)
{ {
queue_print_changes_info(r, playlist.queue, version, const Queue &queue = playlist.queue;
start, end); range.ClipRelaxed(queue.GetLength());
queue_print_changes_info(r, queue, version,
range.start, range.end);
} }
void void
playlist_print_changes_position(Response &r, playlist_print_changes_position(Response &r,
const playlist &playlist, const playlist &playlist,
uint32_t version, 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, queue_print_changes_position(r, playlist.queue, version,
start, end); range.start, range.end);
} }

View File

@ -23,6 +23,7 @@
#include <cstdint> #include <cstdint>
struct playlist; struct playlist;
struct RangeArg;
class SongFilter; class SongFilter;
class Response; class Response;
@ -41,8 +42,7 @@ playlist_print_uris(Response &r, const playlist &playlist);
* Throws #PlaylistError if the range is invalid. * Throws #PlaylistError if the range is invalid.
*/ */
void void
playlist_print_info(Response &r, const playlist &playlist, playlist_print_info(Response &r, const playlist &playlist, RangeArg range);
unsigned start, unsigned end);
/** /**
* Sends the song with the specified id to the client. * Sends the song with the specified id to the client.
@ -73,7 +73,7 @@ playlist_print_find(Response &r, const playlist &playlist,
void void
playlist_print_changes_info(Response &r, const playlist &playlist, playlist_print_changes_info(Response &r, const playlist &playlist,
uint32_t version, uint32_t version,
unsigned start, unsigned end); RangeArg range);
/** /**
* Print changes since the specified playlist version, position only. * Print changes since the specified playlist version, position only.
@ -82,6 +82,6 @@ void
playlist_print_changes_position(Response &r, playlist_print_changes_position(Response &r,
const playlist &playlist, const playlist &playlist,
uint32_t version, uint32_t version,
unsigned start, unsigned end); RangeArg range);
#endif #endif

View File

@ -182,7 +182,7 @@ CommandResult
handle_delete(Client &client, Request args, [[maybe_unused]] Response &r) handle_delete(Client &client, Request args, [[maybe_unused]] Response &r)
{ {
RangeArg range = args.ParseRange(0); RangeArg range = args.ParseRange(0);
client.GetPartition().DeleteRange(range.start, range.end); client.GetPartition().DeleteRange(range);
return CommandResult::OK; return CommandResult::OK;
} }
@ -205,7 +205,7 @@ CommandResult
handle_shuffle([[maybe_unused]] Client &client, Request args, [[maybe_unused]] Response &r) handle_shuffle([[maybe_unused]] Client &client, Request args, [[maybe_unused]] Response &r)
{ {
RangeArg range = args.ParseOptional(0, RangeArg::All()); RangeArg range = args.ParseOptional(0, RangeArg::All());
client.GetPartition().Shuffle(range.start, range.end); client.GetPartition().Shuffle(range);
return CommandResult::OK; return CommandResult::OK;
} }
@ -221,8 +221,7 @@ handle_plchanges(Client &client, Request args, Response &r)
{ {
uint32_t version = ParseCommandArgU32(args.front()); uint32_t version = ParseCommandArgU32(args.front());
RangeArg range = args.ParseOptional(1, RangeArg::All()); RangeArg range = args.ParseOptional(1, RangeArg::All());
playlist_print_changes_info(r, client.GetPlaylist(), version, playlist_print_changes_info(r, client.GetPlaylist(), version, range);
range.start, range.end);
return CommandResult::OK; return CommandResult::OK;
} }
@ -232,7 +231,7 @@ handle_plchangesposid(Client &client, Request args, Response &r)
uint32_t version = ParseCommandArgU32(args.front()); uint32_t version = ParseCommandArgU32(args.front());
RangeArg range = args.ParseOptional(1, RangeArg::All()); RangeArg range = args.ParseOptional(1, RangeArg::All());
playlist_print_changes_position(r, client.GetPlaylist(), version, playlist_print_changes_position(r, client.GetPlaylist(), version,
range.start, range.end); range);
return CommandResult::OK; return CommandResult::OK;
} }
@ -241,8 +240,7 @@ handle_playlistinfo(Client &client, Request args, Response &r)
{ {
RangeArg range = args.ParseOptional(0, RangeArg::All()); RangeArg range = args.ParseOptional(0, RangeArg::All());
playlist_print_info(r, client.GetPlaylist(), playlist_print_info(r, client.GetPlaylist(), range);
range.start, range.end);
return CommandResult::OK; return CommandResult::OK;
} }
@ -253,8 +251,7 @@ handle_playlistid(Client &client, Request args, Response &r)
unsigned id = args.ParseUnsigned(0); unsigned id = args.ParseUnsigned(0);
playlist_print_id(r, client.GetPlaylist(), id); playlist_print_id(r, client.GetPlaylist(), id);
} else { } else {
playlist_print_info(r, client.GetPlaylist(), playlist_print_info(r, client.GetPlaylist(), RangeArg::All());
0, std::numeric_limits<unsigned>::max());
} }
return CommandResult::OK; return CommandResult::OK;
@ -300,7 +297,7 @@ handle_prio(Client &client, Request args, [[maybe_unused]] Response &r)
for (const char *i : args) { for (const char *i : args) {
RangeArg range = ParseCommandArgRange(i); RangeArg range = ParseCommandArgRange(i);
partition.SetPriorityRange(range.start, range.end, priority); partition.SetPriorityRange(range, priority);
} }
return CommandResult::OK; return CommandResult::OK;
@ -332,7 +329,7 @@ handle_move(Client &client, Request args, [[maybe_unused]] Response &r)
} }
int to = args.ParseInt(1); int to = args.ParseInt(1);
client.GetPartition().MoveRange(range.start, range.end, to); client.GetPartition().MoveRange(range, to);
return CommandResult::OK; return CommandResult::OK;
} }

View File

@ -26,6 +26,7 @@
enum TagType : uint8_t; enum TagType : uint8_t;
struct Tag; struct Tag;
struct RangeArg;
class PlayerControl; class PlayerControl;
class DetachedSong; class DetachedSong;
class Database; class Database;
@ -240,7 +241,7 @@ public:
* @param start the position of the first song to delete * @param start the position of the first song to delete
* @param end the position after the last 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 * 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 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, void MoveRange(PlayerControl &pc, RangeArg range, int to);
unsigned end, int to);
void MoveId(PlayerControl &pc, unsigned id, int to); void MoveId(PlayerControl &pc, unsigned id, int to);
@ -262,7 +262,7 @@ public:
void SwapIds(PlayerControl &pc, unsigned id1, unsigned id2); void SwapIds(PlayerControl &pc, unsigned id1, unsigned id2);
void SetPriorityRange(PlayerControl &pc, void SetPriorityRange(PlayerControl &pc,
unsigned start_position, unsigned end_position, RangeArg position_range,
uint8_t priority); uint8_t priority);
void SetPriorityId(PlayerControl &pc, void SetPriorityId(PlayerControl &pc,

View File

@ -27,6 +27,7 @@
#include "Listener.hxx" #include "Listener.hxx"
#include "PlaylistError.hxx" #include "PlaylistError.hxx"
#include "player/Control.hxx" #include "player/Control.hxx"
#include "protocol/RangeArg.hxx"
#include "song/DetachedSong.hxx" #include "song/DetachedSong.hxx"
#include "SongLoader.hxx" #include "SongLoader.hxx"
@ -168,16 +169,13 @@ playlist::SwapIds(PlayerControl &pc, unsigned id1, unsigned id2)
void void
playlist::SetPriorityRange(PlayerControl &pc, playlist::SetPriorityRange(PlayerControl &pc,
unsigned start, unsigned end, RangeArg range,
uint8_t priority) uint8_t priority)
{ {
if (start >= GetLength()) if (!range.CheckClip(GetLength()))
throw PlaylistError::BadRange(); throw PlaylistError::BadRange();
if (end > GetLength()) if (range.IsEmpty())
end = GetLength();
if (start >= end)
return; return;
/* remember "current" and "queued" */ /* remember "current" and "queued" */
@ -187,7 +185,7 @@ playlist::SetPriorityRange(PlayerControl &pc,
/* apply the priority changes */ /* 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" */ /* restore "current" and choose a new "queued" */
@ -206,7 +204,7 @@ playlist::SetPriorityId(PlayerControl &pc,
if (song_position < 0) if (song_position < 0)
throw PlaylistError::NoSuchSong(); throw PlaylistError::NoSuchSong();
SetPriorityRange(pc, song_position, song_position + 1, priority); SetPriorityRange(pc, {unsigned(song_position), song_position + 1U}, priority);
} }
void void
@ -272,22 +270,19 @@ playlist::DeletePosition(PlayerControl &pc, unsigned song)
} }
void 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(); throw PlaylistError::BadRange();
if (end > queue.GetLength()) if (range.IsEmpty())
end = queue.GetLength();
if (start >= end)
return; return;
const DetachedSong *queued_song = GetQueuedSong(); const DetachedSong *queued_song = GetQueuedSong();
do { do {
DeleteInternal(pc, --end, &queued_song); DeleteInternal(pc, --range.end, &queued_song);
} while (end != start); } while (range.end != range.start);
UpdateQueuedSong(pc, queued_song); UpdateQueuedSong(pc, queued_song);
OnModified(); OnModified();
@ -320,17 +315,17 @@ playlist::StaleSong(PlayerControl &pc, const char *uri) noexcept
} }
void void
playlist::MoveRange(PlayerControl &pc, playlist::MoveRange(PlayerControl &pc, RangeArg range, int to)
unsigned start, unsigned end, int to)
{ {
if (!queue.IsValidPosition(start) || !queue.IsValidPosition(end - 1)) if (!queue.IsValidPosition(range.start) ||
!queue.IsValidPosition(range.end - 1))
throw PlaylistError::BadRange(); 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())) (to < 0 && unsigned(std::abs(to)) > GetLength()))
throw PlaylistError::BadRange(); throw PlaylistError::BadRange();
if ((int)start == to) if ((int)range.start == to)
/* nothing happens */ /* nothing happens */
return; return;
@ -347,26 +342,26 @@ playlist::MoveRange(PlayerControl &pc,
because there is no current song */ because there is no current song */
throw PlaylistError::BadRange(); throw PlaylistError::BadRange();
if (start <= (unsigned)currentSong && (unsigned)currentSong < end) if (range.Contains(currentSong))
/* no-op, can't be moved to offset of itself */ /* no-op, can't be moved to offset of itself */
return; return;
to = (currentSong + std::abs(to)) % GetLength(); to = (currentSong + std::abs(to)) % GetLength();
if (start < (unsigned)to) if (range.start < (unsigned)to)
to -= end - start; to -= range.Count();
} }
queue.MoveRange(start, end, to); queue.MoveRange(range.start, range.end, to);
if (!queue.random && current >= 0) { if (!queue.random && current >= 0) {
/* update current */ /* update current */
if (start <= unsigned(current) && unsigned(current) < end) if (range.Contains(current))
current += unsigned(to) - start; current += unsigned(to) - range.start;
else if (unsigned(current) >= end && else if (unsigned(current) >= range.end &&
unsigned(current) <= unsigned(to)) unsigned(current) <= unsigned(to))
current -= end - start; current -= range.Count();
else if (unsigned(current) >= unsigned(to) && else if (unsigned(current) >= unsigned(to) &&
unsigned(current) < start) unsigned(current) < range.start)
current += end - start; current += range.Count();
} }
UpdateQueuedSong(pc, queued_song); UpdateQueuedSong(pc, queued_song);
@ -380,17 +375,16 @@ playlist::MoveId(PlayerControl &pc, unsigned id1, int to)
if (song < 0) if (song < 0)
throw PlaylistError::NoSuchSong(); throw PlaylistError::NoSuchSong();
MoveRange(pc, song, song + 1, to); MoveRange(pc, RangeArg::Single(song), to);
} }
void void
playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept playlist::Shuffle(PlayerControl &pc, RangeArg range)
{ {
if (end > GetLength()) if (!range.CheckClip(GetLength()))
/* correct the "end" offset */ throw PlaylistError::BadRange();
end = GetLength();
if (start + 1 >= end) if (range.HasAtLeast(2))
/* needs at least two entries. */ /* needs at least two entries. */
return; return;
@ -398,17 +392,17 @@ playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept
if (playing && current >= 0) { if (playing && current >= 0) {
unsigned current_position = queue.OrderToPosition(current); unsigned current_position = queue.OrderToPosition(current);
if (current_position >= start && current_position < end) { if (range.Contains(current_position)) {
/* put current playing song first */ /* put current playing song first */
queue.SwapPositions(start, current_position); queue.SwapPositions(range.start, current_position);
if (queue.random) { if (queue.random) {
current = queue.PositionToOrder(start); current = queue.PositionToOrder(range.start);
} else } else
current = start; current = range.start;
/* start shuffle after the current song */ /* start shuffle after the current song */
start++; range.start++;
} }
} else { } else {
/* no playback currently: reset current */ /* no playback currently: reset current */
@ -416,7 +410,7 @@ playlist::Shuffle(PlayerControl &pc, unsigned start, unsigned end) noexcept
current = -1; current = -1;
} }
queue.ShuffleRange(start, end); queue.ShuffleRange(range.start, range.end);
UpdateQueuedSong(pc, queued_song); UpdateQueuedSong(pc, queued_song);
OnModified(); OnModified();

View File

@ -76,12 +76,7 @@ queue_print_changes_info(Response &r, const Queue &queue,
unsigned start, unsigned end) unsigned start, unsigned end)
{ {
assert(start <= end); assert(start <= end);
assert(end <= queue.GetLength());
if (start >= queue.GetLength())
return;
if (end > queue.GetLength())
end = queue.GetLength();
for (unsigned i = start; i < end; i++) for (unsigned i = start; i < end; i++)
if (queue.IsNewerAtPosition(i, version)) if (queue.IsNewerAtPosition(i, version))
@ -94,12 +89,7 @@ queue_print_changes_position(Response &r, const Queue &queue,
unsigned start, unsigned end) unsigned start, unsigned end)
{ {
assert(start <= end); assert(start <= end);
assert(end <= queue.GetLength());
if (start >= queue.GetLength())
return;
if (end > queue.GetLength())
end = queue.GetLength();
for (unsigned i = start; i < end; i++) for (unsigned i = start; i < end; i++)
if (queue.IsNewerAtPosition(i, version)) if (queue.IsNewerAtPosition(i, version))