diff --git a/meson.build b/meson.build index 43be24840..c2a9a1136 100644 --- a/meson.build +++ b/meson.build @@ -277,6 +277,7 @@ sources = [ 'src/TagSave.cxx', 'src/TagFile.cxx', 'src/TagStream.cxx', + 'src/TagAny.cxx', 'src/TimePrint.cxx', 'src/mixer/Volume.cxx', 'src/PlaylistFile.cxx', diff --git a/src/TagAny.cxx b/src/TagAny.cxx new file mode 100644 index 000000000..73566a57e --- /dev/null +++ b/src/TagAny.cxx @@ -0,0 +1,100 @@ +/* + * Copyright 2003-2019 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 "TagAny.hxx" +#include "TagStream.hxx" +#include "TagFile.hxx" +#include "tag/Generic.hxx" +#include "storage/StorageInterface.hxx" +#include "client/Client.hxx" +#include "protocol/Ack.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/Compiler.h" +#include "util/UriExtract.hxx" +#include "LocateUri.hxx" + +static void +TagScanStream(const char *uri, TagHandler &handler) +{ + if (!tag_stream_scan(uri, handler)) + throw ProtocolError(ACK_ERROR_NO_EXIST, "Failed to load file"); +} + +static void +TagScanFile(const Path path_fs, TagHandler &handler) +{ + if (!ScanFileTagsNoGeneric(path_fs, handler)) + throw ProtocolError(ACK_ERROR_NO_EXIST, "Failed to load file"); + + ScanGenericTags(path_fs, handler); +} + +static void +TagScanDatabase(Client &client, const char *uri, TagHandler &handler) +{ +#ifdef ENABLE_DATABASE + const Storage *storage = client.GetStorage(); + if (storage == nullptr) { +#else + (void)client; + (void)uri; + (void)handler; +#endif + throw ProtocolError(ACK_ERROR_NO_EXIST, "No database"); +#ifdef ENABLE_DATABASE + } + + { + const auto path_fs = storage->MapFS(uri); + if (!path_fs.IsNull()) + return TagScanFile(path_fs, handler); + } + + { + const auto absolute_uri = storage->MapUTF8(uri); + if (uri_has_scheme(absolute_uri.c_str())) + return TagScanStream(absolute_uri.c_str(), handler); + } + + throw ProtocolError(ACK_ERROR_NO_EXIST, "No such file"); +#endif +} + +void +TagScanAny(Client &client, const char *uri, TagHandler &handler) +{ + const auto located_uri = LocateUri(UriPluginKind::INPUT, uri, &client +#ifdef ENABLE_DATABASE + , nullptr +#endif + ); + switch (located_uri.type) { + case LocatedUri::Type::ABSOLUTE: + return TagScanStream(located_uri.canonical_uri, handler); + + case LocatedUri::Type::RELATIVE: + return TagScanDatabase(client, located_uri.canonical_uri, + handler); + + case LocatedUri::Type::PATH: + return TagScanFile(located_uri.path, handler); + } + + gcc_unreachable(); +} diff --git a/src/TagAny.hxx b/src/TagAny.hxx new file mode 100644 index 000000000..d0fbf88c5 --- /dev/null +++ b/src/TagAny.hxx @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2019 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. + */ + +#ifndef MPD_TAG_ANY_HXX +#define MPD_TAG_ANY_HXX + +class Client; +class TagHandler; + +/** + * Scan tags in the song file specified by the given URI. The URI may + * be relative to the music directory (the "client" parameter will be + * used to obtain a handle to the #Storage) or absolute. + * + * Throws on error. + */ +void +TagScanAny(Client &client, const char *uri, TagHandler &handler); + +#endif diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 965e596fd..578bf3385 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -30,8 +30,7 @@ #include "util/UriExtract.hxx" #include "tag/Handler.hxx" #include "tag/Generic.hxx" -#include "TagStream.hxx" -#include "TagFile.hxx" +#include "TagAny.hxx" #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileInfo.hxx" @@ -150,66 +149,6 @@ public: } }; -static CommandResult -read_stream_comments(Response &r, const char *uri) -{ - PrintCommentHandler h(r); - if (!tag_stream_scan(uri, h)) { - r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); - return CommandResult::ERROR; - } - - return CommandResult::OK; - -} - -static CommandResult -read_file_comments(Response &r, const Path path_fs) -{ - PrintCommentHandler h(r); - if (!ScanFileTagsNoGeneric(path_fs, h)) { - r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); - return CommandResult::ERROR; - } - - ScanGenericTags(path_fs, h); - - return CommandResult::OK; - -} - -static CommandResult -read_db_comments(Client &client, Response &r, const char *uri) -{ -#ifdef ENABLE_DATABASE - const Storage *storage = client.GetStorage(); - if (storage == nullptr) { -#else - (void)client; - (void)uri; -#endif - r.Error(ACK_ERROR_NO_EXIST, "No database"); - return CommandResult::ERROR; -#ifdef ENABLE_DATABASE - } - - { - AllocatedPath path_fs = storage->MapFS(uri); - if (!path_fs.IsNull()) - return read_file_comments(r, path_fs); - } - - { - const std::string uri2 = storage->MapUTF8(uri); - if (uri_has_scheme(uri2.c_str())) - return read_stream_comments(r, uri2.c_str()); - } - - r.Error(ACK_ERROR_NO_EXIST, "No such file"); - return CommandResult::ERROR; -#endif -} - CommandResult handle_read_comments(Client &client, Request args, Response &r) { @@ -217,23 +156,9 @@ handle_read_comments(Client &client, Request args, Response &r) const char *const uri = args.front(); - const auto located_uri = LocateUri(UriPluginKind::INPUT, uri, &client -#ifdef ENABLE_DATABASE - , nullptr -#endif - ); - switch (located_uri.type) { - case LocatedUri::Type::ABSOLUTE: - return read_stream_comments(r, located_uri.canonical_uri); - - case LocatedUri::Type::RELATIVE: - return read_db_comments(client, r, located_uri.canonical_uri); - - case LocatedUri::Type::PATH: - return read_file_comments(r, located_uri.path); - } - - gcc_unreachable(); + PrintCommentHandler handler(r); + TagScanAny(client, uri, handler); + return CommandResult::OK; } /**