diff --git a/src/common/factory.cpp b/src/common/factory.cpp new file mode 100644 index 0000000..3956add --- /dev/null +++ b/src/common/factory.cpp @@ -0,0 +1,20 @@ +/** + * @file src/common/factory.cpp + * @brief Factory helpers for unsupported platforms. + */ +// local includes +#include "display_device/factory.h" + +#if !defined(_WIN32) && !defined(__APPLE__) + +namespace display_device { + std::unique_ptr makeSettingsManager(const SettingsManagerFactoryConfig &) { + return nullptr; + } + + std::unique_ptr makeDisplayPower() { + return nullptr; + } +} // namespace display_device + +#endif diff --git a/src/common/include/display_device/factory.h b/src/common/include/display_device/factory.h new file mode 100644 index 0000000..6819051 --- /dev/null +++ b/src/common/include/display_device/factory.h @@ -0,0 +1,41 @@ +/** + * @file src/common/include/display_device/factory.h + * @brief Factory helpers for platform display device interfaces. + */ +#pragma once + +// system includes +#include +#include +#include + +// local includes +#include "audio_context_interface.h" +#include "display_power_interface.h" +#include "settings_manager_interface.h" +#include "settings_persistence_interface.h" + +namespace display_device { + /** + * @brief Dependencies and platform-neutral options for creating a settings manager. + */ + struct SettingsManagerFactoryConfig { + std::shared_ptr m_audio_context_api {}; ///< Optional audio context interface. + std::shared_ptr m_settings_persistence_api {}; ///< Optional settings persistence interface. + bool m_throw_on_persistence_load_error {}; ///< Throw when persisted settings cannot be loaded or parsed. + std::optional m_hdr_blank_delay {}; ///< Optional HDR blanking workaround delay on supported platforms. + }; + + /** + * @brief Create the default settings manager for the current platform. + * @param config Dependencies and platform-neutral options. + * @returns A settings manager, or nullptr when the platform is unsupported. + */ + [[nodiscard]] std::unique_ptr makeSettingsManager(const SettingsManagerFactoryConfig &config = {}); + + /** + * @brief Create the default display power manager for the current platform. + * @returns A display power manager, or nullptr when the platform is unsupported. + */ + [[nodiscard]] std::unique_ptr makeDisplayPower(); +} // namespace display_device diff --git a/src/macos/factory.cpp b/src/macos/factory.cpp new file mode 100644 index 0000000..44f7c4f --- /dev/null +++ b/src/macos/factory.cpp @@ -0,0 +1,28 @@ +/** + * @file src/macos/factory.cpp + * @brief Factory helpers for macOS platform interfaces. + */ +// class header include +#include "display_device/factory.h" + +// local includes +#include "display_device/macos/display_power.h" +#include "display_device/macos/mac_api_layer.h" +#include "display_device/macos/mac_display_device.h" +#include "display_device/macos/settings_manager.h" + +namespace display_device { + std::unique_ptr makeSettingsManager(const SettingsManagerFactoryConfig &config) { + auto api_layer {std::make_shared()}; + return std::make_unique( + std::make_shared(api_layer), + config.m_audio_context_api, + std::make_unique(config.m_settings_persistence_api, config.m_throw_on_persistence_load_error), + MacWorkarounds {} + ); + } + + std::unique_ptr makeDisplayPower() { + return std::make_unique(std::make_shared()); + } +} // namespace display_device diff --git a/src/macos/mac_display_device_general.cpp b/src/macos/mac_display_device_general.cpp index 03d27dc..506da51 100644 --- a/src/macos/mac_display_device_general.cpp +++ b/src/macos/mac_display_device_general.cpp @@ -57,7 +57,8 @@ namespace display_device { } } - devices.emplace_back(device_id, display_name, friendly_name, edid, info); + // Keep braced aggregate construction; emplace_back(args...) relies on parenthesized aggregate init, which older libc++ rejects. + devices.push_back(EnumeratedDevice {device_id, display_name, friendly_name, edid, info}); // NOSONAR(cpp:S6003): Direct emplace_back args fail on older toolchains } return devices; diff --git a/src/windows/factory.cpp b/src/windows/factory.cpp new file mode 100644 index 0000000..7ecd799 --- /dev/null +++ b/src/windows/factory.cpp @@ -0,0 +1,30 @@ +/** + * @file src/windows/factory.cpp + * @brief Factory helpers for Windows platform interfaces. + */ +// class header include +#include "display_device/factory.h" + +// local includes +#include "display_device/windows/display_power.h" +#include "display_device/windows/settings_manager.h" +#include "display_device/windows/win_api_layer.h" +#include "display_device/windows/win_display_device.h" + +namespace display_device { + std::unique_ptr makeSettingsManager(const SettingsManagerFactoryConfig &config) { + auto api_layer {std::make_shared()}; + return std::make_unique( + std::make_shared(api_layer), + config.m_audio_context_api, + std::make_unique(config.m_settings_persistence_api, config.m_throw_on_persistence_load_error), + WinWorkarounds { + .m_hdr_blank_delay = config.m_hdr_blank_delay + } + ); + } + + std::unique_ptr makeDisplayPower() { + return std::make_unique(std::make_shared()); + } +} // namespace display_device diff --git a/src/windows/win_display_device_general.cpp b/src/windows/win_display_device_general.cpp index f4f25fd..e75ad59 100644 --- a/src/windows/win_display_device_general.cpp +++ b/src/windows/win_display_device_general.cpp @@ -69,9 +69,11 @@ namespace display_device { m_w_api->getHdrState(best_path) }; - available_devices.emplace_back(device_id, display_name, friendly_name, edid, info); + // Keep braced aggregate construction; emplace_back(args...) relies on parenthesized aggregate init, which older libc++ rejects. + available_devices.push_back(EnumeratedDevice {device_id, display_name, friendly_name, edid, info}); // NOSONAR(cpp:S6003): Direct emplace_back args fail on older toolchains } else { - available_devices.emplace_back(device_id, display_name, friendly_name, edid, std::nullopt); + // Keep braced aggregate construction; emplace_back(args...) relies on parenthesized aggregate init, which older libc++ rejects. + available_devices.push_back(EnumeratedDevice {device_id, display_name, friendly_name, edid, std::nullopt}); // NOSONAR(cpp:S6003): Direct emplace_back args fail on older toolchains } } diff --git a/tests/unit/general/test_factory.cpp b/tests/unit/general/test_factory.cpp new file mode 100644 index 0000000..eec4a9a --- /dev/null +++ b/tests/unit/general/test_factory.cpp @@ -0,0 +1,38 @@ +// system includes +#include + +// local includes +#include "display_device/factory.h" +#include "fixtures/fixtures.h" + +namespace { + using namespace std::chrono_literals; + + // Specialized TEST macro(s) for this test file +#define TEST_S(...) DD_MAKE_TEST(TEST, Factory, __VA_ARGS__) +} // namespace + +TEST_S(MakeSettingsManager) { + display_device::SettingsManagerFactoryConfig config { + .m_hdr_blank_delay = 10ms + }; + + const auto settings_manager {display_device::makeSettingsManager(config)}; + +#if defined(_WIN32) || defined(__APPLE__) + ASSERT_NE(settings_manager, nullptr); + EXPECT_TRUE(settings_manager->resetPersistence()); +#else + EXPECT_EQ(settings_manager, nullptr); +#endif +} + +TEST_S(MakeDisplayPower) { + const auto display_power {display_device::makeDisplayPower()}; + +#if defined(_WIN32) || defined(__APPLE__) + EXPECT_NE(display_power, nullptr); +#else + EXPECT_EQ(display_power, nullptr); +#endif +}