/* * 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()); }