From 07e8c338dfdb203244f294a088eecf68c875678a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 18 Oct 2021 21:51:02 +0200 Subject: [PATCH] command/queue: move position parameter functions to separate library --- meson.build | 1 + src/command/PositionArg.cxx | 103 ++++++++++++++++++++++++++++++++++ src/command/PositionArg.hxx | 32 +++++++++++ src/command/QueueCommands.cxx | 81 +------------------------- 4 files changed, 139 insertions(+), 78 deletions(-) create mode 100644 src/command/PositionArg.cxx create mode 100644 src/command/PositionArg.hxx diff --git a/meson.build b/meson.build index 529f8a829..40ee58763 100644 --- a/meson.build +++ b/meson.build @@ -267,6 +267,7 @@ sources = [ 'src/protocol/ArgParser.cxx', 'src/protocol/Result.cxx', 'src/command/CommandError.cxx', + 'src/command/PositionArg.cxx', 'src/command/AllCommands.cxx', 'src/command/QueueCommands.cxx', 'src/command/TagCommands.cxx', diff --git a/src/command/PositionArg.cxx b/src/command/PositionArg.cxx new file mode 100644 index 000000000..5bb467745 --- /dev/null +++ b/src/command/PositionArg.cxx @@ -0,0 +1,103 @@ +/* + * Copyright 2003-2021 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "PositionArg.hxx" +#include "protocol/Ack.hxx" +#include "protocol/ArgParser.hxx" +#include "protocol/RangeArg.hxx" +#include "queue/Playlist.hxx" + +static unsigned +RequireCurrentPosition(const playlist &p) +{ + int position = p.GetCurrentPosition(); + if (position < 0) + throw ProtocolError(ACK_ERROR_PLAYER_SYNC, + "No current song"); + + return position; +} + +unsigned +ParseInsertPosition(const char *s, const playlist &playlist) +{ + const auto queue_length = playlist.queue.GetLength(); + + if (*s == '+') { + /* after the current song */ + + const unsigned current = RequireCurrentPosition(playlist); + assert(current < queue_length); + + return current + 1 + + ParseCommandArgUnsigned(s + 1, + queue_length - current - 1); + } else if (*s == '-') { + /* before the current song */ + + const unsigned current = RequireCurrentPosition(playlist); + assert(current < queue_length); + + return current - ParseCommandArgUnsigned(s + 1, current); + } else + /* absolute position */ + return ParseCommandArgUnsigned(s, queue_length); +} + +unsigned +ParseMoveDestination(const char *s, const RangeArg range, const playlist &p) +{ + assert(!range.IsEmpty()); + assert(!range.IsOpenEnded()); + + const unsigned queue_length = p.queue.GetLength(); + + if (*s == '+') { + /* after the current song */ + + unsigned current = RequireCurrentPosition(p); + assert(current < queue_length); + if (range.Contains(current)) + throw ProtocolError(ACK_ERROR_ARG, "Cannot move current song relative to itself"); + + if (current >= range.end) + current -= range.Count(); + + return current + 1 + + ParseCommandArgUnsigned(s + 1, + queue_length - current - range.Count()); + } else if (*s == '-') { + /* before the current song */ + + unsigned current = RequireCurrentPosition(p); + assert(current < queue_length); + if (range.Contains(current)) + throw ProtocolError(ACK_ERROR_ARG, "Cannot move current song relative to itself"); + + if (current >= range.end) + current -= range.Count(); + + return current - + ParseCommandArgUnsigned(s + 1, + queue_length - current - range.Count()); + } else + /* absolute position */ + return ParseCommandArgUnsigned(s, + queue_length - range.Count()); +} diff --git a/src/command/PositionArg.hxx b/src/command/PositionArg.hxx new file mode 100644 index 000000000..00c29f7bd --- /dev/null +++ b/src/command/PositionArg.hxx @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2021 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +struct playlist; +struct RangeArg; + +/** + * Throws #ProtocolError on error. + */ +unsigned +ParseInsertPosition(const char *s, const playlist &playlist); + +unsigned +ParseMoveDestination(const char *s, const RangeArg range, const playlist &p); diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx index 7b1861172..338846590 100644 --- a/src/command/QueueCommands.cxx +++ b/src/command/QueueCommands.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "QueueCommands.hxx" +#include "PositionArg.hxx" #include "Request.hxx" #include "protocol/RangeArg.hxx" #include "db/DatabaseQueue.hxx" @@ -43,17 +44,6 @@ #include -static unsigned -RequireCurrentPosition(const playlist &p) -{ - int position = p.GetCurrentPosition(); - if (position < 0) - throw ProtocolError(ACK_ERROR_PLAYER_SYNC, - "No current song"); - - return position; -} - static void AddUri(Client &client, const LocatedUri &uri) { @@ -129,30 +119,8 @@ handle_addid(Client &client, Request args, Response &r) const auto queue_length = partition.playlist.queue.GetLength(); - if (args.size > 1) { - const char *const s = args[1]; - if (*s == '+') { - /* after the current song */ - - const unsigned current = - RequireCurrentPosition(partition.playlist); - assert(current < queue_length); - - to = current + 1 + - ParseCommandArgUnsigned(s + 1, - queue_length - current - 1); - } else if (*s == '-') { - /* before the current song */ - - const unsigned current = - RequireCurrentPosition(partition.playlist); - assert(current < queue_length); - - to = current - ParseCommandArgUnsigned(s + 1, current); - } else - /* absolute position */ - to = args.ParseUnsigned(1, queue_length); - } + if (args.size > 1) + to = ParseInsertPosition(args[1], partition.playlist); const SongLoader loader(client); const unsigned added_position = queue_length; @@ -363,49 +331,6 @@ handle_prioid(Client &client, Request args, [[maybe_unused]] Response &r) return CommandResult::OK; } -static unsigned -ParseMoveDestination(const char *s, const RangeArg range, - const playlist &p) -{ - assert(!range.IsEmpty()); - assert(!range.IsOpenEnded()); - - const unsigned queue_length = p.queue.GetLength(); - - if (*s == '+') { - /* after the current song */ - - unsigned current = RequireCurrentPosition(p); - assert(current < queue_length); - if (range.Contains(current)) - throw ProtocolError(ACK_ERROR_ARG, "Cannot move current song relative to itself"); - - if (current >= range.end) - current -= range.Count(); - - return current + 1 + - ParseCommandArgUnsigned(s + 1, - queue_length - current - range.Count()); - } else if (*s == '-') { - /* before the current song */ - - unsigned current = RequireCurrentPosition(p); - assert(current < queue_length); - if (range.Contains(current)) - throw ProtocolError(ACK_ERROR_ARG, "Cannot move current song relative to itself"); - - if (current >= range.end) - current -= range.Count(); - - return current - - ParseCommandArgUnsigned(s + 1, - queue_length - current - range.Count()); - } else - /* absolute position */ - return ParseCommandArgUnsigned(s, - queue_length - range.Count()); -} - static CommandResult handle_move(Partition &partition, RangeArg range, const char *to) {