From 2e5ca1cbd23f69fe25272d36d6f14b006261ae34 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 14 Oct 2021 14:59:00 +0200 Subject: [PATCH] command/database: add "position" parameter to "findadd" and "searchadd" Closes https://github.com/MusicPlayerDaemon/MPD/issues/888 --- NEWS | 1 + doc/protocol.rst | 7 +++++-- src/command/DatabaseCommands.cxx | 34 +++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 214e54406..f9a4a47c1 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ ver 0.23 (not yet released) - support "listfiles" with arbitrary storage plugins - support relative positions in "addid" - fix relative positions in "move" and "moveid" + - add "position" parameter to "findadd" and "searchadd" * database - proxy: require MPD 0.20 or later - proxy: require libmpdclient 2.11 or later diff --git a/doc/protocol.rst b/doc/protocol.rst index e0a1ce1a0..79c2ed9bd 100644 --- a/doc/protocol.rst +++ b/doc/protocol.rst @@ -1191,15 +1191,18 @@ The music database .. _command_search: -:command:`search {FILTER} [sort {TYPE}] [window {START:END}]` +:command:`search {FILTER} [sort {TYPE}] [window {START:END}] [position POS]` Search the database for songs matching ``FILTER`` (see :ref:`Filters `). Parameters have the same meaning as for :ref:`find `, except that search is not case sensitive. + The ``position`` parameter specifies where the songs will be + inserted. + .. _command_searchadd: -:command:`searchadd {FILTER} [sort {TYPE}] [window {START:END}]` +:command:`searchadd {FILTER} [sort {TYPE}] [window {START:END}] [position POS]` Search the database for songs matching ``FILTER`` (see :ref:`Filters `) and add them to the queue. diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx index 807b75119..a7664907d 100644 --- a/src/command/DatabaseCommands.cxx +++ b/src/command/DatabaseCommands.cxx @@ -19,6 +19,7 @@ #include "DatabaseCommands.hxx" #include "Request.hxx" +#include "Partition.hxx" #include "db/DatabaseQueue.hxx" #include "db/DatabasePlaylist.hxx" #include "db/DatabasePrint.hxx" @@ -70,6 +71,21 @@ ParseSortTag(const char *s) return tag; } +static unsigned +ParseQueuePosition(Request &args, unsigned queue_length) +{ + if (args.size >= 2 && StringIsEqual(args[args.size - 2], "position")) { + unsigned position = args.ParseUnsigned(args.size - 1, + queue_length); + args.pop_back(); + args.pop_back(); + return position; + } + + /* append to the end of the queue by default */ + return queue_length; +} + /** * Convert all remaining arguments to a #DatabaseSelection. * @@ -142,11 +158,27 @@ handle_search(Client &client, Request args, Response &r) static CommandResult handle_match_add(Client &client, Request args, bool fold_case) { + auto &partition = client.GetPartition(); + const auto queue_length = partition.playlist.queue.GetLength(); + const unsigned position = ParseQueuePosition(args, queue_length); + SongFilter filter; const auto selection = ParseDatabaseSelection(args, fold_case, filter); - auto &partition = client.GetPartition(); AddFromDatabase(partition, selection); + + if (position < queue_length) { + const auto new_queue_length = + partition.playlist.queue.GetLength(); + const RangeArg range{queue_length, new_queue_length}; + + try { + partition.MoveRange(range, position); + } catch (...) { + /* ignore - shall we handle it? */ + } + } + return CommandResult::OK; }