diff --git a/Makefile.am b/Makefile.am index 0ddcdff14..11e9d4476 100644 --- a/Makefile.am +++ b/Makefile.am @@ -242,6 +242,7 @@ libmpd_a_SOURCES += \ endif CURL_SOURCES = \ + src/lib/curl/Error.hxx \ src/lib/curl/Delegate.cxx src/lib/curl/Delegate.hxx \ src/lib/curl/Parser.hxx \ src/lib/curl/Version.cxx src/lib/curl/Version.hxx \ @@ -771,6 +772,7 @@ NFS_SOURCES = \ src/lib/nfs/Cancellable.hxx \ src/lib/nfs/Lease.hxx \ src/lib/nfs/Connection.cxx src/lib/nfs/Connection.hxx \ + src/lib/nfs/Error.cxx src/lib/nfs/Error.hxx \ src/lib/nfs/Manager.cxx src/lib/nfs/Manager.hxx \ src/lib/nfs/Glue.cxx src/lib/nfs/Glue.hxx \ src/lib/nfs/Base.cxx src/lib/nfs/Base.hxx \ @@ -1375,6 +1377,7 @@ endif # libinput_a_SOURCES = \ + src/input/Error.cxx src/input/Error.hxx \ src/input/Init.cxx src/input/Init.hxx \ src/input/Registry.cxx src/input/Registry.hxx \ src/input/Open.cxx \ diff --git a/NEWS b/NEWS index c544808f1..42fdadaaf 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,9 @@ ver 0.20.21 (not yet released) * database - proxy: add "password" setting - proxy: support tags "ArtistSort", "AlbumArtistSort", "AlbumSort" + - simple: allow .mpdignore comments only at start of line +* output + - httpd: remove broken DLNA support code ver 0.20.20 (2018/05/22) * protocol diff --git a/python/build/libs.py b/python/build/libs.py index a0818376a..2c47dddb7 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -112,8 +112,8 @@ liblame = AutotoolsProject( ) ffmpeg = FfmpegProject( - 'http://ffmpeg.org/releases/ffmpeg-4.0.tar.xz', - 'ed945daf40b124e77a685893cc025d086f638bc703183460aff49508edb3a43f', + 'http://ffmpeg.org/releases/ffmpeg-4.0.1.tar.xz', + '605f5c01c60db35d3b617a79cabb2c7032412be243554602eeed1b628125c0ee', 'lib/libavcodec.a', [ '--disable-shared', '--enable-static', diff --git a/src/AudioFormat.hxx b/src/AudioFormat.hxx index 4de0ad1c7..d98483085 100644 --- a/src/AudioFormat.hxx +++ b/src/AudioFormat.hxx @@ -23,7 +23,6 @@ #include "pcm/SampleFormat.hxx" #include "Compiler.h" -#include #include #include diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx index 69c4cfab8..390b9e36d 100644 --- a/src/db/update/ExcludeList.cxx +++ b/src/db/update/ExcludeList.cxx @@ -26,8 +26,7 @@ #include "ExcludeList.hxx" #include "fs/Path.hxx" #include "fs/NarrowPath.hxx" -#include "fs/io/TextFile.hxx" -#include "system/Error.hxx" +#include "input/TextInputStream.hxx" #include "util/StringStrip.hxx" #include "Log.hxx" @@ -36,35 +35,29 @@ #include #include +inline void +ExcludeList::ParseLine(char *line) noexcept +{ + char *p = Strip(line); + if (*p != 0 && *p != '#') + patterns.emplace_front(p); +} + bool -ExcludeList::LoadFile(Path path_fs) noexcept -try { +ExcludeList::Load(InputStreamPtr is) +{ #ifdef HAVE_CLASS_GLOB - TextFile file(path_fs); + TextInputStream tis(std::move(is)); char *line; - while ((line = file.ReadLine()) != nullptr) { - char *p = strchr(line, '#'); - if (p != nullptr) - *p = 0; - - p = Strip(line); - if (*p != 0) - patterns.emplace_front(p); - } + while ((line = tis.ReadLine()) != nullptr) + ParseLine(line); #else /* not implemented */ (void)path_fs; #endif return true; -} catch (const std::system_error &e) { - if (!IsFileNotFound(e)) - LogError(e); - return false; -} catch (...) { - LogError(std::current_exception()); - return false; } bool diff --git a/src/db/update/ExcludeList.hxx b/src/db/update/ExcludeList.hxx index 793a3a162..4a851a7dc 100644 --- a/src/db/update/ExcludeList.hxx +++ b/src/db/update/ExcludeList.hxx @@ -28,6 +28,7 @@ #include "check.h" #include "Compiler.h" #include "fs/Glob.hxx" +#include "input/Ptr.hxx" #ifdef HAVE_CLASS_GLOB #include @@ -62,13 +63,16 @@ public: /** * Loads and parses a .mpdignore file. */ - bool LoadFile(Path path_fs) noexcept; + bool Load(InputStreamPtr is); /** * Checks whether one of the patterns in the .mpdignore file matches * the specified file name. */ bool Check(Path name_fs) const noexcept; + +private: + void ParseLine(char *line) noexcept; }; diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index 0961d2e5d..f04319849 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -36,6 +36,8 @@ #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "storage/FileInfo.hxx" +#include "input/InputStream.hxx" +#include "input/Error.hxx" #include "util/Alloc.hxx" #include "util/StringCompare.hxx" #include "util/UriUtil.hxx" @@ -346,11 +348,15 @@ UpdateWalk::UpdateDirectory(Directory &directory, ExcludeList child_exclude_list(exclude_list); - { - const auto exclude_path_fs = - storage.MapChildFS(directory.GetPath(), ".mpdignore"); - if (!exclude_path_fs.IsNull()) - child_exclude_list.LoadFile(exclude_path_fs); + try { + Mutex mutex; + auto is = InputStream::OpenReady(PathTraitsUTF8::Build(storage.MapUTF8(directory.GetPath()).c_str(), + ".mpdignore").c_str(), + mutex); + child_exclude_list.Load(std::move(is)); + } catch (...) { + if (!IsFileNotFound(std::current_exception())) + LogError(std::current_exception()); } if (!child_exclude_list.IsEmpty()) diff --git a/src/input/Error.cxx b/src/input/Error.cxx new file mode 100644 index 000000000..3db1f26f1 --- /dev/null +++ b/src/input/Error.cxx @@ -0,0 +1,53 @@ +/* + * Copyright 2003-2018 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 "config.h" +#include "Error.hxx" +#include "system/Error.hxx" + +#ifdef ENABLE_CURL +#include "lib/curl/Error.hxx" +#endif + +#ifdef ENABLE_NFS +#include "lib/nfs/Error.hxx" +#include +#endif + +bool +IsFileNotFound(std::exception_ptr ep) +{ + try { + std::rethrow_exception(ep); + } catch (const std::system_error &e) { + return IsFileNotFound(e); +#ifdef ENABLE_CURL + } catch (const HttpStatusError &e) { + return e.GetStatus() == 404; +#endif +#ifdef ENABLE_NFS + } catch (const NfsClientError &e) { + return e.GetCode() == NFS3ERR_NOENT; +#endif + } catch (...) { + } + + return false; +} + diff --git a/src/input/Error.hxx b/src/input/Error.hxx new file mode 100644 index 000000000..b52b9d06b --- /dev/null +++ b/src/input/Error.hxx @@ -0,0 +1,37 @@ +/* + * Copyright 2003-2018 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 INPUT_ERROR_HXX +#define INPUT_ERROR_HXX + +#include "check.h" +#include "Compiler.h" + +#include + +/** + * Was this exception thrown because the requested file does not + * exist? This function attempts to recognize exceptions thrown by + * various input plugins. + */ +gcc_pure +bool +IsFileNotFound(std::exception_ptr e); + +#endif diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index f808a5c21..dcf87eb87 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "CurlInputPlugin.hxx" +#include "lib/curl/Error.hxx" #include "lib/curl/Easy.hxx" #include "lib/curl/Global.hxx" #include "lib/curl/Init.hxx" @@ -194,7 +195,9 @@ CurlInputStream::OnHeaders(unsigned status, assert(!icy || !icy->IsDefined()); if (status < 200 || status >= 300) - throw FormatRuntimeError("got HTTP status %ld", status); + throw HttpStatusError(status, + StringFormat<40>("got HTTP status %u", + status).c_str()); const std::lock_guard protect(mutex); diff --git a/src/lib/curl/Error.hxx b/src/lib/curl/Error.hxx new file mode 100644 index 000000000..4bd68e0c8 --- /dev/null +++ b/src/lib/curl/Error.hxx @@ -0,0 +1,42 @@ +/* + * Copyright 2003-2018 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 CURL_ERROR_HXX +#define CURL_ERROR_HXX + +#include + +/** + * Thrown when an unsuccessful status was received from the HTTP + * server. + */ +class HttpStatusError : public std::runtime_error { + unsigned status; + +public: + template + explicit HttpStatusError(unsigned _status, M &&_msg) noexcept + :std::runtime_error(std::forward(_msg)), status(_status) {} + + unsigned GetStatus() const noexcept { + return status; + } +}; + +#endif diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index 2afcf094c..8abfd9bc6 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "Connection.hxx" +#include "Error.hxx" #include "Lease.hxx" #include "Callback.hxx" #include "event/Loop.hxx" @@ -139,7 +140,7 @@ NfsConnection::CancellableCallback::Callback(int err, void *data) noexcept if (err >= 0) cb.OnNfsCallback((unsigned)err, data); else - cb.OnNfsError(std::make_exception_ptr(std::runtime_error((const char *)data))); + cb.OnNfsError(std::make_exception_ptr(NfsClientError(-err, (const char *)data))); } else { if (open) { /* a nfs_open_async() call was cancelled - to diff --git a/src/lib/nfs/Error.cxx b/src/lib/nfs/Error.cxx new file mode 100644 index 000000000..942e6cabf --- /dev/null +++ b/src/lib/nfs/Error.cxx @@ -0,0 +1,76 @@ +/* + * Copyright 2007-2017 Content Management AG + * All rights reserved. + * + * author: Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Error.hxx" +#include "util/StringFormat.hxx" + +extern "C" { +#include +} + +#include +#include + +static StringBuffer<256> +FormatNfsClientError(struct nfs_context *nfs, const char *msg) noexcept +{ + assert(msg != nullptr); + + const char *msg2 = nfs_get_error(nfs); + return StringFormat<256>("%s: %s", msg, msg2); +} + +NfsClientError::NfsClientError(struct nfs_context *nfs, const char *msg) noexcept + :std::runtime_error(FormatNfsClientError(nfs, msg).c_str()), + code(0) {} + +static StringBuffer<256> +FormatNfsClientError(int err, struct nfs_context *nfs, void *data, + const char *msg) noexcept +{ + assert(msg != nullptr); + assert(err < 0); + + const char *msg2 = (const char *)data; + if (data == nullptr || *(const char *)data == 0) { + msg2 = nfs_get_error(nfs); + if (msg2 == nullptr) + msg2 = strerror(-err); + } + + return StringFormat<256>("%s: %s", msg, msg2); +} + +NfsClientError::NfsClientError(int err, struct nfs_context *nfs, void *data, + const char *msg) noexcept + :std::runtime_error(FormatNfsClientError(err, nfs, data, msg).c_str()), + code(-err) {} diff --git a/src/lib/nfs/Error.hxx b/src/lib/nfs/Error.hxx new file mode 100644 index 000000000..73ab13e5d --- /dev/null +++ b/src/lib/nfs/Error.hxx @@ -0,0 +1,58 @@ +/* + * Copyright 2007-2017 Content Management AG + * All rights reserved. + * + * author: Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NFS_ERROR_HXX +#define NFS_ERROR_HXX + +#include + +class NfsClientError : public std::runtime_error { + int code; + +public: + explicit NfsClientError(const char *_msg) noexcept + :std::runtime_error(_msg), code(0) {} + + NfsClientError(int _code, const char *_msg) noexcept + :std::runtime_error(_msg), code(_code) {} + + NfsClientError(struct nfs_context *nfs, const char *msg) noexcept; + + NfsClientError(int err, struct nfs_context *nfs, void *data, + const char *msg) noexcept; + + int GetCode() const noexcept { + return code; + } +}; + +#endif diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx index f6b1d88f5..adc44afce 100644 --- a/src/output/plugins/RoarOutputPlugin.cxx +++ b/src/output/plugins/RoarOutputPlugin.cxx @@ -35,6 +35,8 @@ #include #undef new +#include + class RoarOutput final : AudioOutput { const std::string host, name; diff --git a/src/output/plugins/httpd/HttpdClient.cxx b/src/output/plugins/httpd/HttpdClient.cxx index 0ef8306be..d9bbc22d1 100644 --- a/src/output/plugins/httpd/HttpdClient.cxx +++ b/src/output/plugins/httpd/HttpdClient.cxx @@ -113,15 +113,6 @@ HttpdClient::HandleLine(const char *line) return true; } - if (StringEqualsCaseASCII(line, "transferMode.dlna.org: Streaming", 32)) { - /* Send as dlna */ - dlna_streaming_requested = true; - /* metadata is not supported by dlna streaming, so disable it */ - metadata_supported = false; - metadata_requested = false; - return true; - } - /* expect more request headers */ return true; } @@ -139,22 +130,7 @@ HttpdClient::SendResponse() assert(state == State::RESPONSE); - if (dlna_streaming_requested) { - snprintf(buffer, sizeof(buffer), - "HTTP/1.1 206 OK\r\n" - "Content-Type: %s\r\n" - "Content-Length: 10000\r\n" - "Content-RangeX: 0-1000000/1000000\r\n" - "transferMode.dlna.org: Streaming\r\n" - "Accept-Ranges: bytes\r\n" - "Connection: close\r\n" - "realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n" - "contentFeatures.dlna.org: DLNA.ORG_OP=01;DLNA.ORG_CI=0\r\n" - "\r\n", - httpd.content_type); - response = buffer; - - } else if (metadata_requested) { + if (metadata_requested) { allocated = icy_server_metadata_header(httpd.name, httpd.genre, httpd.website, diff --git a/src/output/plugins/httpd/HttpdClient.hxx b/src/output/plugins/httpd/HttpdClient.hxx index 8b7502d84..9d061f43d 100644 --- a/src/output/plugins/httpd/HttpdClient.hxx +++ b/src/output/plugins/httpd/HttpdClient.hxx @@ -83,11 +83,6 @@ class HttpdClient final */ bool head_method = false; - /** - * If DLNA streaming was an option. - */ - bool dlna_streaming_requested = false; - /* ICY */ /** diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx index d2093a188..605900c1c 100644 --- a/src/pcm/ConfiguredResampler.cxx +++ b/src/pcm/ConfiguredResampler.cxx @@ -35,6 +35,7 @@ #include "SoxrResampler.hxx" #endif +#include #include enum class SelectedResampler { diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx index 3d928e41d..4c3fe8614 100644 --- a/src/pcm/PcmExport.cxx +++ b/src/pcm/PcmExport.cxx @@ -32,6 +32,8 @@ #include "PcmDop.hxx" #endif +#include + void PcmExport::Open(SampleFormat sample_format, unsigned _channels, Params params) noexcept