command/playlist: allow range in "playlistmove"
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1689
This commit is contained in:
parent
f4adbdbe31
commit
04e60d67ae
1
NEWS
1
NEWS
|
@ -2,6 +2,7 @@ ver 0.24 (not yet released)
|
|||
* protocol
|
||||
- new command "searchcount" (case-insensitive "count")
|
||||
- "playlistfind"/"playlistsearch" have "sort" and "window" parameters
|
||||
- allow range in "playlistmove"
|
||||
- "save" can append to or replace an existing playlist
|
||||
- filter "prio" (for "playlistfind"/"playlistsearch")
|
||||
- limit "player" idle events to the current partition
|
||||
|
|
|
@ -994,8 +994,9 @@ remote playlists (absolute URI with a supported scheme).
|
|||
|
||||
.. _command_playlistmove:
|
||||
|
||||
:command:`playlistmove {NAME} {FROM} {TO}`
|
||||
Moves the song at position ``FROM`` in
|
||||
:command:`playlistmove {NAME} [{FROM} | {START:END}] {TO}`
|
||||
Moves the song at position ``FROM`` or range of songs
|
||||
at ``START:END`` [#since_0_24]_ in
|
||||
the playlist `NAME.m3u` to the
|
||||
position ``TO``.
|
||||
|
||||
|
|
|
@ -296,18 +296,41 @@ PlaylistFileEditor::Insert(std::size_t i, const DetachedSong &song)
|
|||
Insert(i, uri);
|
||||
}
|
||||
|
||||
void
|
||||
PlaylistFileEditor::MoveIndex(unsigned src, unsigned dest)
|
||||
static PlaylistFileContents
|
||||
CutRange(PlaylistFileContents &src, RangeArg range) noexcept
|
||||
{
|
||||
if (src >= contents.size() || dest >= contents.size())
|
||||
PlaylistFileContents dest;
|
||||
dest.reserve(range.Count());
|
||||
|
||||
const auto begin = std::next(src.begin(), range.start);
|
||||
const auto end = std::next(src.begin(), range.end);
|
||||
|
||||
for (auto i = begin; i != end; ++i)
|
||||
dest.emplace_back(std::move(*i));
|
||||
|
||||
src.erase(begin, end);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void
|
||||
InsertRange(PlaylistFileContents &dest, PlaylistFileContents::iterator pos,
|
||||
PlaylistFileContents &&src) noexcept
|
||||
{
|
||||
dest.reserve(dest.size() + src.size());
|
||||
|
||||
for (auto &i : src)
|
||||
pos = std::next(dest.emplace(pos, std::move(i)));
|
||||
}
|
||||
|
||||
void
|
||||
PlaylistFileEditor::MoveIndex(RangeArg src, unsigned dest)
|
||||
{
|
||||
if (src.end > contents.size() || dest > contents.size() - src.Count())
|
||||
throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range");
|
||||
|
||||
const auto src_i = std::next(contents.begin(), src);
|
||||
auto value = std::move(*src_i);
|
||||
contents.erase(src_i);
|
||||
|
||||
const auto dest_i = std::next(contents.begin(), dest);
|
||||
contents.insert(dest_i, std::move(value));
|
||||
auto tmp = CutRange(contents, src);
|
||||
InsertRange(contents, std::next(contents.begin(), dest), std::move(tmp));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
void Insert(std::size_t i, const char *uri);
|
||||
void Insert(std::size_t i, const DetachedSong &song);
|
||||
|
||||
void MoveIndex(unsigned src, unsigned dest);
|
||||
void MoveIndex(RangeArg src, unsigned dest);
|
||||
void RemoveIndex(unsigned i);
|
||||
void RemoveRange(RangeArg range);
|
||||
|
||||
|
|
|
@ -202,10 +202,16 @@ handle_playlistmove([[maybe_unused]] Client &client,
|
|||
Request args, [[maybe_unused]] Response &r)
|
||||
{
|
||||
const char *const name = args.front();
|
||||
unsigned from = args.ParseUnsigned(1);
|
||||
|
||||
RangeArg from = args.ParseRange(1);
|
||||
if (from.IsOpenEnded()) {
|
||||
r.Error(ACK_ERROR_ARG, "Open-ended range not supported");
|
||||
return CommandResult::ERROR;
|
||||
}
|
||||
|
||||
unsigned to = args.ParseUnsigned(2);
|
||||
|
||||
if (from == to)
|
||||
if (from.IsEmpty() || from.start == to)
|
||||
/* this doesn't check whether the playlist exists, but
|
||||
what the hell.. */
|
||||
return CommandResult::OK;
|
||||
|
|
Loading…
Reference in New Issue