diff --git a/NEWS b/NEWS index 18f6adad4..65aa42e56 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,7 @@ ver 0.23 (not yet released) * tags - new tags "ComposerSort", "Ensemble", "Movement", "MovementNumber", and "Location" -ver 0.22.7 (not yet released) +ver 0.22.7 (2021/05/19) * protocol - don't use glibc extension to parse time stamps - optimize the "albumart" command diff --git a/meson.build b/meson.build index 6e333d43a..a4bab2405 100644 --- a/meson.build +++ b/meson.build @@ -140,10 +140,29 @@ endif if is_windows common_cppflags += [ - '-DWIN32_LEAN_AND_MEAN', + # enable Windows Vista APIs '-DWINVER=0x0600', '-D_WIN32_WINNT=0x0600', - '-DSTRICT', + + # enable Unicode support (TCHAR=wchar_t) in the Windows API (macro + # "UNICODE) and the C library (macro "_UNICODE") '-DUNICODE', '-D_UNICODE', + + # enable strict type checking in the Windows API headers + '-DSTRICT', + + # reduce header bloat by disabling obscure and obsolete Windows + # APIs + '-DWIN32_LEAN_AND_MEAN', + + # disable more Windows APIs which are not used by MPD + '-DNOGDI', '-DNOBITMAP', '-DNOCOMM', + '-DNOUSER', + + # reduce COM header bloat + '-DCOM_NO_WINDOWS_H', + + # disable Internet Explorer specific APIs + '-D_WIN32_IE=0', ] subdir('win32') diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx index 5c46c90e4..e046d5ca4 100644 --- a/src/CommandLine.cxx +++ b/src/CommandLine.cxx @@ -114,7 +114,7 @@ static void version() printf("Music Player Daemon " VERSION " (%s)" "\n" "Copyright 2003-2007 Warren Dukes \n" - "Copyright 2008-2018 Max Kellermann \n" + "Copyright 2008-2021 Max Kellermann \n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", GIT_VERSION); diff --git a/src/client/Response.cxx b/src/client/Response.cxx index 0c9145a50..b582d6bbc 100644 --- a/src/client/Response.cxx +++ b/src/client/Response.cxx @@ -61,7 +61,12 @@ Response::WriteBinary(ConstBuffer payload) noexcept { assert(payload.size <= client.binary_limit); - return Format("binary: %zu\n", payload.size) && + return +#ifdef _WIN32 + Format("binary: %lu\n", (unsigned long)payload.size) && +#else + Format("binary: %zu\n", payload.size) && +#endif Write(payload.data, payload.size) && Write("\n"); } diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index a09d2bfad..1c8b6ee28 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -228,7 +228,12 @@ read_stream_art(Response &r, const char *uri, size_t offset) read_size = is->Read(lock, buffer.get(), buffer_size); } +#ifdef _WIN32 + r.Format("size: %lu\n", (unsigned long)art_file_size); +#else r.Format("size: %" PRIoffset "\n", art_file_size); +#endif + r.WriteBinary({buffer.get(), read_size}); return CommandResult::OK; @@ -310,7 +315,11 @@ public: return; } +#ifdef _WIN32 + response.Format("size: %lu\n", (unsigned long)buffer.size); +#else response.Format("size: %zu\n", buffer.size); +#endif if (mime_type != nullptr) response.Format("type: %s\n", mime_type); diff --git a/src/fs/DirectoryReader.hxx b/src/fs/DirectoryReader.hxx index abf63957e..3ee1fd876 100644 --- a/src/fs/DirectoryReader.hxx +++ b/src/fs/DirectoryReader.hxx @@ -24,7 +24,7 @@ #ifdef _WIN32 -#include +#include #include /** diff --git a/src/fs/Glob.cxx b/src/fs/Glob.cxx new file mode 100644 index 000000000..f2119bd9a --- /dev/null +++ b/src/fs/Glob.cxx @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifdef _WIN32 +// COM needs the "MSG" typedef, and shlwapi.h includes COM headers +#undef NOUSER +#endif + +#include "Glob.hxx" + +#ifdef _WIN32 +#include + +bool +Glob::Check(const char *name_fs) const noexcept +{ + return PathMatchSpecA(name_fs, pattern.c_str()); +} + +#endif diff --git a/src/fs/Glob.hxx b/src/fs/Glob.hxx index 0a2e9abfc..65e3a9e1f 100644 --- a/src/fs/Glob.hxx +++ b/src/fs/Glob.hxx @@ -24,45 +24,44 @@ #ifdef HAVE_FNMATCH #define HAVE_CLASS_GLOB -#include #include #elif defined(_WIN32) #define HAVE_CLASS_GLOB -#include -#include #endif #ifdef HAVE_CLASS_GLOB #include "util/Compiler.h" +#include + /** * A pattern that matches file names. It may contain shell wildcards * (asterisk and question mark). */ class Glob { -#if defined(HAVE_FNMATCH) || defined(_WIN32) std::string pattern; -#endif public: -#if defined(HAVE_FNMATCH) || defined(_WIN32) explicit Glob(const char *_pattern) :pattern(_pattern) {} - Glob(Glob &&other) - :pattern(std::move(other.pattern)) {} -#endif + Glob(Glob &&other) noexcept = default; + Glob &operator=(Glob &&other) noexcept = default; gcc_pure - bool Check(const char *name_fs) const noexcept { -#ifdef HAVE_FNMATCH - return fnmatch(pattern.c_str(), name_fs, 0) == 0; -#elif defined(_WIN32) - return PathMatchSpecA(name_fs, pattern.c_str()); -#endif - } + bool Check(const char *name_fs) const noexcept; }; -#endif +#ifdef HAVE_FNMATCH + +inline bool +Glob::Check(const char *name_fs) const noexcept +{ + return fnmatch(pattern.c_str(), name_fs, 0) == 0; +} + +#endif + +#endif /* HAVE_CLASS_GLOB */ #endif diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx index 05bee122b..7190f7a95 100644 --- a/src/fs/StandardDirectory.cxx +++ b/src/fs/StandardDirectory.cxx @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef _WIN32 +#undef NOUSER // COM needs the "MSG" typedef, and shlobj.h includes COM headers +#endif + #include "StandardDirectory.hxx" #include "FileSystem.hxx" #include "XDG.hxx" diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx index d377f08ea..10c614831 100644 --- a/src/fs/io/FileOutputStream.hxx +++ b/src/fs/io/FileOutputStream.hxx @@ -42,7 +42,10 @@ #include #ifdef _WIN32 -#include +#include +#include // for HWND (needed by winbase.h) +#include // for INVALID_HANDLE_VALUE +#include // for FILE_END #endif #if defined(__linux__) && !defined(ANDROID) diff --git a/src/fs/io/FileReader.hxx b/src/fs/io/FileReader.hxx index bee39cc9a..5be332b72 100644 --- a/src/fs/io/FileReader.hxx +++ b/src/fs/io/FileReader.hxx @@ -35,7 +35,10 @@ #include "util/Compiler.h" #ifdef _WIN32 -#include +#include +#include // for INVALID_HANDLE_VALUE +#include // for HWND (needed by winbase.h) +#include // for FILE_CURRENT #else #include "io/UniqueFileDescriptor.hxx" #endif diff --git a/src/fs/meson.build b/src/fs/meson.build index 483df7694..2e483e7ae 100644 --- a/src/fs/meson.build +++ b/src/fs/meson.build @@ -3,6 +3,7 @@ fs_sources = [ 'Traits.cxx', 'Config.cxx', 'Charset.cxx', + 'Glob.cxx', 'Path.cxx', 'Path2.cxx', 'AllocatedPath.cxx', diff --git a/src/mixer/plugins/WasapiMixerPlugin.cxx b/src/mixer/plugins/WasapiMixerPlugin.cxx index d0145405a..19bc11c08 100644 --- a/src/mixer/plugins/WasapiMixerPlugin.cxx +++ b/src/mixer/plugins/WasapiMixerPlugin.cxx @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#undef NOUSER // COM needs the "MSG" typedef + #include "output/plugins/wasapi/ForMixer.hxx" #include "output/plugins/wasapi/AudioClient.hxx" #include "output/plugins/wasapi/Device.hxx" diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx index 1f4f180d8..66b3dc3b5 100644 --- a/src/output/plugins/WinmmOutputPlugin.cxx +++ b/src/output/plugins/WinmmOutputPlugin.cxx @@ -28,6 +28,10 @@ #include #include +#include +#include +#include // for INFINITE + #include #include diff --git a/src/output/plugins/WinmmOutputPlugin.hxx b/src/output/plugins/WinmmOutputPlugin.hxx index e5d249f38..5e29121b8 100644 --- a/src/output/plugins/WinmmOutputPlugin.hxx +++ b/src/output/plugins/WinmmOutputPlugin.hxx @@ -26,7 +26,7 @@ #include "util/Compiler.h" -#include +#include #include struct WinmmOutput; diff --git a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx index 97b66a998..e331195e9 100644 --- a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx +++ b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#undef NOUSER // COM needs the "MSG" typedef + #include "WasapiOutputPlugin.hxx" #include "ForMixer.hxx" #include "AudioClient.hxx" @@ -607,10 +609,10 @@ WasapiOutput::DoOpen(AudioFormat &audio_format) throw MakeHResultError(result, "Unable to get device period"); } FormatDebug(wasapi_output_domain, - "Default device period: %I64u ns, Minimum device period: " - "%I64u ns", - ns(hundred_ns(default_device_period)).count(), - ns(hundred_ns(min_device_period)).count()); + "Default device period: %lu ns, Minimum device period: " + "%lu ns", + (unsigned long)ns(hundred_ns(default_device_period)).count(), + (unsigned long)ns(hundred_ns(min_device_period)).count()); REFERENCE_TIME buffer_duration; if (Exclusive()) { @@ -619,8 +621,8 @@ WasapiOutput::DoOpen(AudioFormat &audio_format) const REFERENCE_TIME align = hundred_ns(ms(50)).count(); buffer_duration = (align / default_device_period) * default_device_period; } - FormatDebug(wasapi_output_domain, "Buffer duration: %I64u ns", - size_t(ns(hundred_ns(buffer_duration)).count())); + FormatDebug(wasapi_output_domain, "Buffer duration: %lu ns", + (unsigned long)ns(hundred_ns(buffer_duration)).count()); if (Exclusive()) { if (HRESULT result = client->Initialize( @@ -639,8 +641,8 @@ WasapiOutput::DoOpen(AudioFormat &audio_format) SampleRate()); FormatDebug( wasapi_output_domain, - "Aligned buffer duration: %I64u ns", - size_t(ns(hundred_ns(buffer_duration)).count())); + "Aligned buffer duration: %lu ns", + (unsigned long)ns(hundred_ns(buffer_duration)).count()); client.reset(); client = Activate(*device); result = client->Initialize( diff --git a/src/system/Error.hxx b/src/system/Error.hxx index 289ceeaf8..aa017966b 100644 --- a/src/system/Error.hxx +++ b/src/system/Error.hxx @@ -47,7 +47,9 @@ FormatSystemError(std::error_code code, const char *fmt, #ifdef _WIN32 -#include +#include // for GetLastError() +#include // for HWND (needed by winbase.h) +#include // for FormatMessageA() static inline std::system_error MakeLastError(DWORD code, const char *msg) noexcept diff --git a/src/system/FatalError.cxx b/src/system/FatalError.cxx index e892c5472..c8473bb69 100644 --- a/src/system/FatalError.cxx +++ b/src/system/FatalError.cxx @@ -27,7 +27,9 @@ #include #ifdef _WIN32 -#include +#include // for GetLastError() +#include // for HWND (needed by winbase.h) +#include // for FormatMessageA() #else #include #endif diff --git a/src/thread/CriticalSection.hxx b/src/thread/CriticalSection.hxx index 3e311738e..4cc140739 100644 --- a/src/thread/CriticalSection.hxx +++ b/src/thread/CriticalSection.hxx @@ -30,7 +30,7 @@ #ifndef THREAD_CRITICAL_SECTION_HXX #define THREAD_CRITICAL_SECTION_HXX -#include +#include /** * Wrapper for a CRITICAL_SECTION, backend for the Mutex class. diff --git a/src/thread/Id.hxx b/src/thread/Id.hxx index f7ba58c64..04471a54a 100644 --- a/src/thread/Id.hxx +++ b/src/thread/Id.hxx @@ -33,7 +33,7 @@ #include "util/Compiler.h" #ifdef _WIN32 -#include +#include #else #include #endif diff --git a/src/thread/Thread.hxx b/src/thread/Thread.hxx index ff9abbdd4..071f9d7bd 100644 --- a/src/thread/Thread.hxx +++ b/src/thread/Thread.hxx @@ -26,7 +26,7 @@ #include #ifdef _WIN32 -#include +#include #else #include #endif diff --git a/src/thread/WindowsCond.hxx b/src/thread/WindowsCond.hxx index 7c0b19a1f..0f49f71d5 100644 --- a/src/thread/WindowsCond.hxx +++ b/src/thread/WindowsCond.hxx @@ -32,6 +32,9 @@ #include "CriticalSection.hxx" +#include // for HWND (needed by winbase.h) +#include // for INFINITE + #include #include diff --git a/src/util/HugeAllocator.hxx b/src/util/HugeAllocator.hxx index bb6a12726..786a2a722 100644 --- a/src/util/HugeAllocator.hxx +++ b/src/util/HugeAllocator.hxx @@ -77,7 +77,7 @@ void HugeDiscard(void *p, size_t size) noexcept; #elif defined(_WIN32) -#include +#include WritableBuffer HugeAllocate(size_t size); diff --git a/src/util/RuntimeError.hxx b/src/util/RuntimeError.hxx index 3d523013b..962bad67b 100644 --- a/src/util/RuntimeError.hxx +++ b/src/util/RuntimeError.hxx @@ -35,6 +35,12 @@ #include +#ifdef __clang__ +#pragma GCC diagnostic push +// TODO: fix this warning properly +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + template static inline std::runtime_error FormatRuntimeError(const char *fmt, Args&&... args) noexcept @@ -53,4 +59,8 @@ FormatInvalidArgument(const char *fmt, Args&&... args) noexcept return std::invalid_argument(buffer); } +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif + #endif diff --git a/src/win32/Com.hxx b/src/win32/Com.hxx index 173b0fcc9..15b3b9d98 100644 --- a/src/win32/Com.hxx +++ b/src/win32/Com.hxx @@ -21,8 +21,9 @@ #define MPD_WIN32_COM_HXX #include "HResult.hxx" -#include -#include + +#include +#include // for COINIT_APARTMENTTHREADED // RAII for Microsoft Component Object Model(COM) // https://docs.microsoft.com/en-us/windows/win32/api/_com/ diff --git a/src/win32/ComHeapPtr.hxx b/src/win32/ComHeapPtr.hxx index 737bc6551..08d4401f6 100644 --- a/src/win32/ComHeapPtr.hxx +++ b/src/win32/ComHeapPtr.hxx @@ -23,7 +23,8 @@ #include #include #include -#include + +#include // RAII for CoTaskMemAlloc and CoTaskMemFree // https://docs.microsoft.com/zh-tw/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemalloc diff --git a/src/win32/ComPtr.hxx b/src/win32/ComPtr.hxx index c7efa88b8..3c652e2f3 100644 --- a/src/win32/ComPtr.hxx +++ b/src/win32/ComPtr.hxx @@ -21,10 +21,12 @@ #define MPD_WIN32_COMPTR_HXX #include "win32/HResult.hxx" + #include #include #include -#include + +#include // RAII for Object in Microsoft Component Object Model(COM) // https://docs.microsoft.com/zh-tw/windows/win32/api/_com/ diff --git a/src/win32/ComWorker.cxx b/src/win32/ComWorker.cxx index c5ada8c91..15150f76d 100644 --- a/src/win32/ComWorker.cxx +++ b/src/win32/ComWorker.cxx @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#undef NOUSER // COM needs the "MSG" typedef + #include "ComWorker.hxx" #include "Com.hxx" #include "thread/Name.hxx" diff --git a/src/win32/ComWorker.hxx b/src/win32/ComWorker.hxx index d4c410652..4016d9939 100644 --- a/src/win32/ComWorker.hxx +++ b/src/win32/ComWorker.hxx @@ -26,8 +26,6 @@ #include -#include - // Worker thread for all COM operation class COMWorker { Thread thread{BIND_THIS_METHOD(Work)}; diff --git a/src/win32/HResult.cxx b/src/win32/HResult.cxx index 0daa80163..a4e04caa6 100644 --- a/src/win32/HResult.cxx +++ b/src/win32/HResult.cxx @@ -17,6 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef _WIN32 +// COM needs the "MSG" typedef, and audiopolicy.h includes COM headers +#undef NOUSER +#endif + #include "HResult.hxx" #include "system/Error.hxx" @@ -25,6 +30,46 @@ #include #include +#include // needed by audiopolicy.h if COM_NO_WINDOWS_H is defined +#include + +std::string_view +HRESULTToString(HRESULT result) noexcept +{ + using namespace std::literals; + switch (result) { +#define C(x) \ +case x: \ + return #x##sv + C(AUDCLNT_E_ALREADY_INITIALIZED); + C(AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL); + C(AUDCLNT_E_BUFFER_ERROR); + C(AUDCLNT_E_BUFFER_OPERATION_PENDING); + C(AUDCLNT_E_BUFFER_SIZE_ERROR); + C(AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED); + C(AUDCLNT_E_BUFFER_TOO_LARGE); + C(AUDCLNT_E_CPUUSAGE_EXCEEDED); + C(AUDCLNT_E_DEVICE_INVALIDATED); + C(AUDCLNT_E_DEVICE_IN_USE); + C(AUDCLNT_E_ENDPOINT_CREATE_FAILED); + C(AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED); + C(AUDCLNT_E_INVALID_DEVICE_PERIOD); + C(AUDCLNT_E_OUT_OF_ORDER); + C(AUDCLNT_E_SERVICE_NOT_RUNNING); + C(AUDCLNT_E_UNSUPPORTED_FORMAT); + C(AUDCLNT_E_WRONG_ENDPOINT_TYPE); + C(AUDCLNT_E_NOT_INITIALIZED); + C(AUDCLNT_E_NOT_STOPPED); + C(CO_E_NOTINITIALIZED); + C(E_INVALIDARG); + C(E_OUTOFMEMORY); + C(E_POINTER); + C(NO_ERROR); +#undef C + } + return std::string_view(); +} + std::string HResultCategory::message(int Errcode) const { diff --git a/src/win32/HResult.hxx b/src/win32/HResult.hxx index 9bf612727..5ed92732c 100644 --- a/src/win32/HResult.hxx +++ b/src/win32/HResult.hxx @@ -25,42 +25,11 @@ #include #include -#include +#include -constexpr std::string_view HRESULTToString(HRESULT result) { - using namespace std::literals; - switch (result) { -#define C(x) \ -case x: \ - return #x##sv - C(AUDCLNT_E_ALREADY_INITIALIZED); - C(AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL); - C(AUDCLNT_E_BUFFER_ERROR); - C(AUDCLNT_E_BUFFER_OPERATION_PENDING); - C(AUDCLNT_E_BUFFER_SIZE_ERROR); - C(AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED); - C(AUDCLNT_E_BUFFER_TOO_LARGE); - C(AUDCLNT_E_CPUUSAGE_EXCEEDED); - C(AUDCLNT_E_DEVICE_INVALIDATED); - C(AUDCLNT_E_DEVICE_IN_USE); - C(AUDCLNT_E_ENDPOINT_CREATE_FAILED); - C(AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED); - C(AUDCLNT_E_INVALID_DEVICE_PERIOD); - C(AUDCLNT_E_OUT_OF_ORDER); - C(AUDCLNT_E_SERVICE_NOT_RUNNING); - C(AUDCLNT_E_UNSUPPORTED_FORMAT); - C(AUDCLNT_E_WRONG_ENDPOINT_TYPE); - C(AUDCLNT_E_NOT_INITIALIZED); - C(AUDCLNT_E_NOT_STOPPED); - C(CO_E_NOTINITIALIZED); - C(E_INVALIDARG); - C(E_OUTOFMEMORY); - C(E_POINTER); - C(NO_ERROR); -#undef C - } - return std::string_view(); -} +gcc_const +std::string_view +HRESULTToString(HRESULT result) noexcept; static inline const std::error_category &hresult_category() noexcept; class HResultCategory : public std::error_category { diff --git a/src/win32/PropVariant.hxx b/src/win32/PropVariant.hxx index 54da5e988..3f733441c 100644 --- a/src/win32/PropVariant.hxx +++ b/src/win32/PropVariant.hxx @@ -20,6 +20,7 @@ #ifndef MPD_WIN32_PROPVARIANT_HXX #define MPD_WIN32_PROPVARIANT_HXX +#include // needed by propidl.h if COM_NO_WINDOWS_H is defined #include class AllocatedString; diff --git a/src/win32/WinEvent.hxx b/src/win32/WinEvent.hxx index 7b3305c37..e757fbbae 100644 --- a/src/win32/WinEvent.hxx +++ b/src/win32/WinEvent.hxx @@ -20,7 +20,10 @@ #ifndef MPD_WIN32_WINEVENT_HXX #define MPD_WIN32_WINEVENT_HXX -#include +#include +#include +#include // for HWND (needed by winbase.h) +#include // for INFINITE // RAII for Windows unnamed event object // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventw