diff --git a/meson.build b/meson.build index e374db54c..6e333d43a 100644 --- a/meson.build +++ b/meson.build @@ -311,7 +311,6 @@ sources = [ if is_windows sources += [ 'src/win32/Win32Main.cxx', - 'src/win32/ComWorker.cxx', ] endif @@ -349,6 +348,7 @@ subdir('src/system') subdir('src/thread') subdir('src/net') subdir('src/event') +subdir('src/win32') subdir('src/apple') diff --git a/src/output/plugins/WasapiOutputPlugin.cxx b/src/output/plugins/WasapiOutputPlugin.cxx index 99f7dacf4..84d23dd12 100644 --- a/src/output/plugins/WasapiOutputPlugin.cxx +++ b/src/output/plugins/WasapiOutputPlugin.cxx @@ -155,7 +155,7 @@ public: void Finish() noexcept { return SetStatus(Status::FINISH); } void Play() noexcept { return SetStatus(Status::PLAY); } void Pause() noexcept { return SetStatus(Status::PAUSE); } - void WaitDataPoped() noexcept { data_poped.Wait(INFINITE); } + void WaitDataPoped() noexcept { data_poped.Wait(); } void CheckException() { if (error.occur.load()) { auto err = std::exchange(error.ptr, nullptr); @@ -269,7 +269,7 @@ void WasapiOutputThread::Work() noexcept { COM com{true}; while (true) { try { - event.Wait(INFINITE); + event.Wait(); Status current_state = status.load(); if (current_state == Status::FINISH) { @@ -322,7 +322,7 @@ void WasapiOutputThread::Work() noexcept { } catch (...) { error.ptr = std::current_exception(); error.occur.store(true); - error.thrown.Wait(INFINITE); + error.thrown.Wait(); } } } diff --git a/src/output/plugins/meson.build b/src/output/plugins/meson.build index a7534ff17..d06f55141 100644 --- a/src/output/plugins/meson.build +++ b/src/output/plugins/meson.build @@ -159,6 +159,7 @@ if is_windows wasapi_dep = [ c_compiler.find_library('ksuser', required: true), c_compiler.find_library('ole32', required: true), + win32_dep, ] else wasapi_dep = dependency('', required: false) diff --git a/src/thread/WindowsFuture.hxx b/src/thread/WindowsFuture.hxx index f5d304a1e..e9082a63c 100644 --- a/src/thread/WindowsFuture.hxx +++ b/src/thread/WindowsFuture.hxx @@ -22,7 +22,7 @@ #include "CriticalSection.hxx" #include "WindowsCond.hxx" -#include + #include #include diff --git a/src/win32/ComWorker.cxx b/src/win32/ComWorker.cxx index d708dffbe..702c2c427 100644 --- a/src/win32/ComWorker.cxx +++ b/src/win32/ComWorker.cxx @@ -16,27 +16,20 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "ComWorker.hxx" -#include "Log.hxx" -#include "thread/Name.hxx" -#include "util/Domain.hxx" -#include "win32/Com.hxx" -namespace { -static constexpr Domain com_worker_domain("com_worker"); -} +#include "ComWorker.hxx" +#include "Com.hxx" +#include "thread/Name.hxx" Mutex COMWorker::mutex; unsigned int COMWorker::reference_count = 0; std::optional COMWorker::thread; void COMWorker::COMWorkerThread::Work() noexcept { - FormatDebug(com_worker_domain, "Working thread started"); SetThreadName("COM Worker"); COM com{true}; while (true) { if (!running_flag.test_and_set()) { - FormatDebug(com_worker_domain, "Working thread ended"); return; } while (!spsc_buffer.empty()) { diff --git a/src/win32/ComWorker.hxx b/src/win32/ComWorker.hxx index cd3bd5db6..10f2123a4 100644 --- a/src/win32/ComWorker.hxx +++ b/src/win32/ComWorker.hxx @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Music Player Daemon Project + * Copyright 2020-2021 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,16 +20,15 @@ #ifndef MPD_WIN32_COM_WORKER_HXX #define MPD_WIN32_COM_WORKER_HXX -#include -#include -#include -#include - +#include "WinEvent.hxx" #include "thread/Future.hxx" #include "thread/Mutex.hxx" #include "thread/Thread.hxx" -#include "win32/WinEvent.hxx" -#include + +#include +#include +#include + #include // Worker thread for all COM operation diff --git a/src/win32/HResult.cxx b/src/win32/HResult.cxx new file mode 100644 index 000000000..a40116a1b --- /dev/null +++ b/src/win32/HResult.cxx @@ -0,0 +1,57 @@ +/* + * Copyright 2020-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 "HResult.hxx" + +#include +#include +#include +#include + +std::string +HResultCategory::message(int Errcode) const +{ + const auto msg = HRESULTToString(Errcode); + if (!msg.empty()) + return std::string(msg); + + char buffer[11]; // "0x12345678\0" + int size = snprintf(buffer, sizeof(buffer), "0x%1x", Errcode); + assert(2 <= size && size <= 10); + return std::string(buffer, size); +} + +std::system_error +FormatHResultError(HRESULT result, const char *fmt, ...) noexcept +{ + std::va_list args1, args2; + va_start(args1, fmt); + va_copy(args2, args1); + + const int size = vsnprintf(nullptr, 0, fmt, args1); + va_end(args1); + assert(size >= 0); + + auto buffer = std::make_unique(size + 1); + vsprintf(buffer.get(), fmt, args2); + va_end(args2); + + return std::system_error(std::error_code(result, hresult_category()), + std::string(buffer.get(), size)); +} diff --git a/src/win32/HResult.hxx b/src/win32/HResult.hxx index 2bc851f73..2f48c08f2 100644 --- a/src/win32/HResult.hxx +++ b/src/win32/HResult.hxx @@ -22,13 +22,8 @@ #include "util/Compiler.h" -#include -#include -#include -#include #include #include -#include #include @@ -69,16 +64,7 @@ static inline const std::error_category &hresult_category() noexcept; class HResultCategory : public std::error_category { public: const char *name() const noexcept override { return "HRESULT"; } - std::string message(int Errcode) const override { - const auto msg = HRESULTToString(Errcode); - if (!msg.empty()) { - return std::string(msg); - } - char buffer[11]; // "0x12345678\0" - int size = snprintf(buffer, sizeof(buffer), "0x%1x", Errcode); - assert(2 <= size && size <= 10); - return std::string(buffer, size); - } + std::string message(int Errcode) const override; std::error_condition default_error_condition(int code) const noexcept override { return std::error_condition(code, hresult_category()); } @@ -88,22 +74,7 @@ static inline const std::error_category &hresult_category() noexcept { return hresult_category_instance; } -gcc_printf(2, 3) static inline std::runtime_error - FormatHResultError(HRESULT result, const char *fmt, ...) noexcept { - std::va_list args1, args2; - va_start(args1, fmt); - va_copy(args2, args1); - - const int size = vsnprintf(nullptr, 0, fmt, args1); - va_end(args1); - assert(size >= 0); - - auto buffer = std::make_unique(size + 1); - vsprintf(buffer.get(), fmt, args2); - va_end(args2); - - return std::system_error(std::error_code(result, hresult_category()), - std::string(buffer.get(), size)); -} +gcc_printf(2, 3) std::system_error +FormatHResultError(HRESULT result, const char *fmt, ...) noexcept; #endif diff --git a/src/win32/WinEvent.cxx b/src/win32/WinEvent.cxx new file mode 100644 index 000000000..b203a6bb3 --- /dev/null +++ b/src/win32/WinEvent.cxx @@ -0,0 +1,28 @@ +/* + * Copyright 2020-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 "WinEvent.hxx" +#include "system/Error.hxx" + +WinEvent::WinEvent() + :event(CreateEventW(nullptr, false, false, nullptr)) +{ + if (!event) + throw FormatLastError("Error creating events"); +} diff --git a/src/win32/WinEvent.hxx b/src/win32/WinEvent.hxx index 127855f91..7b3305c37 100644 --- a/src/win32/WinEvent.hxx +++ b/src/win32/WinEvent.hxx @@ -20,7 +20,6 @@ #ifndef MPD_WIN32_WINEVENT_HXX #define MPD_WIN32_WINEVENT_HXX -#include "system/Error.hxx" #include // RAII for Windows unnamed event object @@ -28,11 +27,11 @@ class WinEvent { public: - WinEvent() : event(CreateEventW(nullptr, false, false, nullptr)) { - if (!event) { - throw FormatLastError("Error creating events"); - } - } + /** + * Throws on error. + */ + WinEvent(); + ~WinEvent() noexcept { CloseHandle(event); } WinEvent(WinEvent &&) = delete; WinEvent(const WinEvent &) = delete; @@ -41,7 +40,7 @@ public: HANDLE handle() noexcept { return event; } - DWORD Wait(DWORD milliseconds) noexcept { + DWORD Wait(DWORD milliseconds=INFINITE) noexcept { return WaitForSingleObject(event, milliseconds); } diff --git a/src/win32/meson.build b/src/win32/meson.build new file mode 100644 index 000000000..5f8eaf6b7 --- /dev/null +++ b/src/win32/meson.build @@ -0,0 +1,19 @@ +if not is_windows + win32_dep = dependency('', required: false) + subdir_done() +endif + +win32 = static_library( + 'win32', + 'ComWorker.cxx', + 'HResult.cxx', + 'WinEvent.cxx', + include_directories: inc, +) + +win32_dep = declare_dependency( + link_with: win32, + dependencies: [ + thread_dep, + ], +) diff --git a/test/TestLookupFile.cxx b/test/TestLookupFile.cxx index be6d85cfb..aab42ac20 100644 --- a/test/TestLookupFile.cxx +++ b/test/TestLookupFile.cxx @@ -8,23 +8,23 @@ TEST(ArchiveTest, Lookup) { - EXPECT_THROW(LookupFile(Path::FromFS("")), std::system_error); + EXPECT_THROW(LookupFile(Path::FromFS(PATH_LITERAL(""))), std::system_error); - EXPECT_FALSE(LookupFile(Path::FromFS("."))); + EXPECT_FALSE(LookupFile(Path::FromFS(PATH_LITERAL(".")))); - EXPECT_FALSE(LookupFile(Path::FromFS("config.h"))); + EXPECT_FALSE(LookupFile(Path::FromFS(PATH_LITERAL("config.h")))); - EXPECT_THROW(LookupFile(Path::FromFS("src/foo/bar")), std::system_error); + EXPECT_THROW(LookupFile(Path::FromFS(PATH_LITERAL("src/foo/bar"))), std::system_error); fclose(fopen("dummy", "w")); - auto result = LookupFile(Path::FromFS("dummy/foo/bar")); + auto result = LookupFile(Path::FromFS(PATH_LITERAL("dummy/foo/bar"))); EXPECT_TRUE(result); - EXPECT_STREQ(result.archive.c_str(), "dummy"); - EXPECT_STREQ(result.inside.c_str(), "foo/bar"); + EXPECT_STREQ(result.archive.c_str(), PATH_LITERAL("dummy")); + EXPECT_STREQ(result.inside.c_str(), PATH_LITERAL("foo/bar")); - result = LookupFile(Path::FromFS("config.h/foo/bar")); + result = LookupFile(Path::FromFS(PATH_LITERAL("config.h/foo/bar"))); EXPECT_TRUE(result); - EXPECT_STREQ(result.archive.c_str(), "config.h"); - EXPECT_STREQ(result.inside.c_str(), "foo/bar"); + EXPECT_STREQ(result.archive.c_str(), PATH_LITERAL("config.h")); + EXPECT_STREQ(result.inside.c_str(), PATH_LITERAL("foo/bar")); } diff --git a/test/run_convert.cxx b/test/run_convert.cxx index d4323fcbb..3cba693fd 100644 --- a/test/run_convert.cxx +++ b/test/run_convert.cxx @@ -28,6 +28,7 @@ #include "pcm/AudioFormat.hxx" #include "pcm/Convert.hxx" #include "fs/Path.hxx" +#include "fs/NarrowPath.hxx" #include "util/ConstBuffer.hxx" #include "util/StaticFifoBuffer.hxx" #include "util/OptionDef.hxx" @@ -47,7 +48,7 @@ struct CommandLine { AudioFormat in_audio_format, out_audio_format; - Path config_path = nullptr; + FromNarrowPath config_path; bool verbose = false; }; @@ -71,7 +72,7 @@ ParseCommandLine(int argc, char **argv) while (auto o = option_parser.Next()) { switch (Option(o.index)) { case OPTION_CONFIG: - c.config_path = Path::FromFS(o.value); + c.config_path = o.value; break; case OPTION_VERBOSE: