From 7a80ccbaea4b1f642cc78f72c64f472f0a053dbd Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Sun, 28 Jul 2024 16:33:39 +0300 Subject: [PATCH] simplify implementation --- src/display_device.cpp | 40 ++++++------ src/display_device.h | 93 +++++++-------------------- src/main.cpp | 2 +- src/platform/macos/input.cpp | 2 +- src/platform/windows/display_base.cpp | 2 +- src/video.cpp | 6 +- 6 files changed, 52 insertions(+), 93 deletions(-) diff --git a/src/display_device.cpp b/src/display_device.cpp index 74f35459ce5..4072305faed 100644 --- a/src/display_device.cpp +++ b/src/display_device.cpp @@ -10,6 +10,9 @@ #include #include +// local includes +#include "platform/common.h" + // platform-specific includes #ifdef _WIN32 #include @@ -19,6 +22,15 @@ namespace display_device { namespace { + /** + * @brief A global for the settings manager interface whose lifetime is managed by `display_device::init()`. + */ + std::unique_ptr> SM_INSTANCE; + + /** + * @brief Construct a settings manager interface to manage display device settings. + * @return An interface or nullptr if the OS does not support the interface. + */ std::unique_ptr make_settings_manager() { #ifdef _WIN32 @@ -33,23 +45,17 @@ namespace display_device { } } // namespace - session_t & - session_t::get() { - static session_t session; - return session; - } - std::unique_ptr - session_t::init() { + init() { // We can support re-init without any issues, however we should make sure to cleanup first! - get().impl = nullptr; + SM_INSTANCE = nullptr; // If we fail to create settings manager, this means platform is not supported and // we will need to provided error-free passtrough in other methods if (auto settings_manager { make_settings_manager() }) { - get().impl = std::make_unique>(std::move(settings_manager)); + SM_INSTANCE = std::make_unique>(std::move(settings_manager)); - const auto available_devices { get().impl->execute([](auto &settings_iface) { return settings_iface.enumAvailableDevices(); }) }; + const auto available_devices { SM_INSTANCE->execute([](auto &settings_iface) { return settings_iface.enumAvailableDevices(); }) }; BOOST_LOG(info) << "Currently available display devices:\n" << toJson(available_devices); @@ -60,21 +66,19 @@ namespace display_device { public: ~deinit_t() override { // TODO: In the upcoming PR, execute recovery once here - get().impl = nullptr; + SM_INSTANCE = nullptr; } }; return std::make_unique(); } std::string - session_t::map_output_name(const std::string &output_name) const { - if (impl) { - return impl->execute([&output_name](auto &settings_iface) { return settings_iface.getDisplayName(output_name); }); + map_output_name(const std::string &output_name) { + if (!SM_INSTANCE) { + // Fallback to giving back the output name if the platform is not supported. + return output_name; } - // Fallback to giving back the output name if the platform is not supported. - return output_name; + return SM_INSTANCE->execute([&output_name](auto &settings_iface) { return settings_iface.getDisplayName(output_name); }); } - - session_t::session_t() = default; } // namespace display_device diff --git a/src/display_device.h b/src/display_device.h index c436bfa21f0..6562f5a3dcc 100644 --- a/src/display_device.h +++ b/src/display_device.h @@ -4,81 +4,36 @@ */ #pragma once -// local includes -#include "platform/common.h" +// lib includes +#include // forward declarations -namespace display_device { - template - class RetryScheduler; - class SettingsManagerInterface; -} // namespace display_device +namespace platf { + class deinit_t; +} // namespace platf namespace display_device { /** - * @brief A singleton class for managing the display device configuration for the whole Sunshine session. + * @brief Initialize the implementation and perform the initial state recovery (if needed). + * @returns A deinit_t instance that performs cleanup when destroyed. * - * This class is meant to be an entry point for applying the configuration and reverting it later - * from within the various places in the Sunshine's source code. + * @examples + * const auto init_guard { display_device::init() }; + * @examples_end */ - class session_t { - public: - /** - * @brief Get the singleton instance. - * @returns Singleton instance for the class. - * - * @examples - * session_t& session { session_t::get() }; - * @examples_end - */ - [[nodiscard]] static session_t & - get(); - - /** - * @brief Initialize the singleton and perform the initial state recovery (if needed). - * @returns A deinit_t instance that performs cleanup when destroyed. - * - * @examples - * const auto session_guard { session_t::init() }; - * @examples_end - */ - [[nodiscard]] static std::unique_ptr - init(); - - /** - * @brief Map the output name to a specific display. - * @param output_name The user-configurable output name. - * @returns Mapped display name or empty string if the output name could not be mapped. - * - * @examples - * session_t& session { session_t::get() }; - * const auto mapped_name_config { session.get_display_name(config::video.output_name) }; - * const auto mapped_name_custom { session.get_display_name("{some-device-id}") }; - * @examples_end - */ - [[nodiscard]] std::string - map_output_name(const std::string &output_name) const; - - /** - * @brief A deleted copy constructor for singleton pattern. - * @note Public to ensure better error message. - */ - session_t(session_t const &) = delete; + std::unique_ptr + init(); - /** - * @brief A deleted assignment operator for singleton pattern. - * @note Public to ensure better error message. - */ - void - operator=(session_t const &) = delete; - - private: - /** - * @brief A private constructor to ensure the singleton pattern. - * @note Cannot be defaulted in declaration because of forward declared RetryScheduler. - */ - explicit session_t(); - - std::unique_ptr> impl; /**< Platform specific interface for managing settings (with retry functionality). */ - }; + /** + * @brief Map the output name to a specific display. + * @param output_name The user-configurable output name. + * @returns Mapped display name or empty string if the output name could not be mapped. + * + * @examples + * const auto mapped_name_config { map_output_name(config::video.output_name) }; + * const auto mapped_name_custom { map_output_name("{some-device-id}") }; + * @examples_end + */ + std::string + map_output_name(const std::string &output_name); } // namespace display_device diff --git a/src/main.cpp b/src/main.cpp index 1969760d743..bc8b5c8c22d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -125,7 +125,7 @@ main(int argc, char *argv[]) { // Adding guard here first as it also performs recovery after crash, // otherwise people could theoretically end up without display output. // It also should be destroyed before forced shutdown to expedite the cleanup. - auto display_device_deinit_guard = display_device::session_t::init(); + auto display_device_deinit_guard = display_device::init(); if (!display_device_deinit_guard) { BOOST_LOG(error) << "Display device session failed to initialize"sv; } diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index b231b9a0b2c..91099483707 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -539,7 +539,7 @@ const KeyCodeMap kKeyCodesMap[] = { // Default to main display macos_input->display = CGMainDisplayID(); - auto output_name = display_device::session_t::get().map_output_name(config::video.output_name); + auto output_name = display_device::map_output_name(config::video.output_name); // If output_name is set, try to find the display with that display id if (!output_name.empty()) { uint32_t max_display = 32; diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index 63f779e8dc3..7a5ba7d7c92 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -1080,7 +1080,7 @@ namespace platf { BOOST_LOG(debug) << "Detecting monitors..."sv; // We must set the GPU preference before calling any DXGI APIs! - const auto output_name { display_device::session_t::get().map_output_name(config::video.output_name) }; + const auto output_name { display_device::map_output_name(config::video.output_name) }; if (!dxgi::probe_for_gpu_preference(output_name)) { BOOST_LOG(warning) << "Failed to set GPU preference. Capture may not work!"sv; } diff --git a/src/video.cpp b/src/video.cpp index 724d936975f..f51555811fa 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -968,7 +968,7 @@ namespace video { void refresh_displays(platf::mem_type_e dev_type, std::vector &display_names, int ¤t_display_index) { // It is possible that the output name may be empty even if it wasn't before (device disconnected) or vice-versa - const auto output_name { display_device::session_t::get().map_output_name(config::video.output_name) }; + const auto output_name { display_device::map_output_name(config::video.output_name) }; std::string current_display_name; // If we have a current display index, let's start with that @@ -2291,7 +2291,7 @@ namespace video { bool validate_encoder(encoder_t &encoder, bool expect_failure) { - const auto output_name { display_device::session_t::get().map_output_name(config::video.output_name) }; + const auto output_name { display_device::map_output_name(config::video.output_name) }; std::shared_ptr disp; BOOST_LOG(info) << "Trying encoder ["sv << encoder.name << ']'; @@ -2595,7 +2595,7 @@ namespace video { } if (chosen_encoder == nullptr) { - const auto output_name { display_device::session_t::get().map_output_name(config::video.output_name) }; + const auto output_name { display_device::map_output_name(config::video.output_name) }; BOOST_LOG(fatal) << "Unable to find display or encoder during startup."sv; if (!config::video.adapter_name.empty() || !output_name.empty()) { BOOST_LOG(fatal) << "Please ensure your manually chosen GPU and monitor are connected and powered on."sv;