diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 522e3705..8ac8b713 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -9,19 +9,21 @@ #include "AL/ALAudio.hpp" #include "NoAudio.hpp" #include "debug/Logger.hpp" +#include "util/ObjectsKeeper.hpp" static debug::Logger logger("audio"); -namespace audio { +using namespace audio; + +namespace { static speakerid_t nextId = 1; static Backend* backend; static std::unordered_map> speakers; static std::unordered_map> streams; static std::vector> channels; + static util::ObjectsKeeper objects_keeper {}; } -using namespace audio; - Channel::Channel(std::string name) : name(std::move(name)) { } @@ -148,7 +150,8 @@ public: } }; -void audio::initialize(bool enabled) { +void audio::initialize(bool enabled, AudioSettings& settings) { + enabled = enabled && settings.enabled.get(); if (enabled) { logger.info() << "initializing ALAudio backend"; backend = ALAudio::create().release(); @@ -160,7 +163,22 @@ void audio::initialize(bool enabled) { logger.info() << "initializing NoAudio backend"; backend = NoAudio::create().release(); } - create_channel("master"); + struct { + std::string name; + NumberSetting* setting; + } builtin_channels[] { + {"master", &settings.volumeMaster}, + {"regular", &settings.volumeRegular}, + {"music", &settings.volumeMusic}, + {"ambient", &settings.volumeAmbient}, + {"ui", &settings.volumeUI} + }; + for (auto& channel : builtin_channels) { + create_channel(channel.name); + objects_keeper.keepAlive(channel.setting->observe([=](auto value) { + audio::get_channel(channel.name)->setVolume(value * value); + }, true)); + } } std::unique_ptr audio::load_PCM(const fs::path& file, bool headerOnly) { @@ -442,4 +460,5 @@ void audio::close() { speakers.clear(); delete backend; backend = nullptr; + objects_keeper.clearKeepedObjects(); } diff --git a/src/audio/audio.hpp b/src/audio/audio.hpp index a37ebeea..37ae8e00 100644 --- a/src/audio/audio.hpp +++ b/src/audio/audio.hpp @@ -6,6 +6,7 @@ #include #include "typedefs.hpp" +#include "settings.hpp" namespace fs = std::filesystem; @@ -357,7 +358,7 @@ namespace audio { /// @brief Initialize audio system or use no audio mode /// @param enabled try to initialize actual audio - void initialize(bool enabled); + void initialize(bool enabled, AudioSettings& settings); /// @brief Load audio file info and PCM data /// @param file audio file diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index c9de5a64..73704468 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -52,15 +52,6 @@ static debug::Logger logger("engine"); namespace fs = std::filesystem; -static void create_channel(Engine* engine, std::string name, NumberSetting& setting) { - if (name != "master") { - audio::create_channel(name); - } - engine->keepAlive(setting.observe([=](auto value) { - audio::get_channel(name)->setVolume(value*value); - }, true)); -} - static std::unique_ptr load_icon(const fs::path& resdir) { try { auto file = resdir / fs::u8path("textures/misc/icon.png"); @@ -73,12 +64,23 @@ static std::unique_ptr load_icon(const fs::path& resdir) { return nullptr; } -Engine::Engine(CoreParameters coreParameters) - : params(std::move(coreParameters)), - settings(), - settingsHandler({settings}), - interpreter(std::make_unique()), - network(network::Network::create(settings.network)) { +Engine::Engine() = default; + +static std::unique_ptr engine; + +Engine& Engine::getInstance() { + if (!engine) { + engine = std::make_unique(); + } + return *engine; +} + +void Engine::initialize(CoreParameters coreParameters) { + params = std::move(coreParameters); + settingsHandler = std::make_unique(settings); + interpreter = std::make_unique(); + network = network::Network::create(settings.network); + logger.info() << "engine version: " << ENGINE_VERSION_STRING; if (params.headless) { logger.info() << "headless mode is enabled"; @@ -110,12 +112,7 @@ Engine::Engine(CoreParameters coreParameters) menus::create_version_label(*this); } } - audio::initialize(settings.audio.enabled.get() && !params.headless); - create_channel(this, "master", settings.audio.volumeMaster); - create_channel(this, "regular", settings.audio.volumeRegular); - create_channel(this, "music", settings.audio.volumeMusic); - create_channel(this, "ambient", settings.audio.volumeAmbient); - create_channel(this, "ui", settings.audio.volumeUI); + audio::initialize(!params.headless, settings.audio); bool langNotSet = settings.ui.language.get() == "auto"; if (langNotSet) { @@ -140,7 +137,7 @@ void Engine::loadSettings() { logger.info() << "loading settings"; std::string text = files::read_string(settings_file); try { - toml::parse(settingsHandler, settings_file.string(), text); + toml::parse(*settingsHandler, settings_file.string(), text); } catch (const parsing_error& err) { logger.error() << err.errorLog(); throw; @@ -222,7 +219,7 @@ void Engine::renderFrame() { void Engine::saveSettings() { logger.info() << "saving settings"; - files::write_string(paths.getSettingsFile(), toml::stringify(settingsHandler)); + files::write_string(paths.getSettingsFile(), toml::stringify(*settingsHandler)); if (!params.headless) { logger.info() << "saving bindings"; files::write_string(paths.getControlsFile(), Events::writeBindings()); @@ -255,6 +252,10 @@ Engine::~Engine() { logger.info() << "engine finished"; } +void Engine::terminate() { + engine.reset(); +} + EngineController* Engine::getController() { return controller.get(); } @@ -511,7 +512,7 @@ std::shared_ptr Engine::getScreen() { } SettingsHandler& Engine::getSettingsHandler() { - return settingsHandler; + return *settingsHandler; } network::Network& Engine::getNetwork() { diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 406d420a..d4cbf40a 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -58,9 +58,9 @@ using OnWorldOpen = std::function, int64_t)>; class Engine : public util::ObjectsKeeper { CoreParameters params; EngineSettings settings; - SettingsHandler settingsHandler; EnginePaths paths; + std::unique_ptr settingsHandler; std::unique_ptr assets; std::shared_ptr screen; std::vector contentPacks; @@ -82,9 +82,15 @@ class Engine : public util::ObjectsKeeper { void updateHotkeys(); void loadAssets(); public: - Engine(CoreParameters coreParameters); + Engine(); ~Engine(); + static Engine& getInstance(); + + void initialize(CoreParameters coreParameters); + + static void terminate(); + /// @brief Start the engine void run(); diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 6bae272d..d5243153 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -637,8 +637,9 @@ static std::shared_ptr readInventory(UiXmlReader& reader, const xml::xml static std::shared_ptr readPageBox(UiXmlReader& reader, const xml::xmlelement& element) { auto menu = std::make_shared(); - // FIXME - menu->setPageLoader(scripting::engine->getGUI()->getMenu()->getPageLoader()); + menu->setPageLoader( + Engine::getInstance().getGUI()->getMenu()->getPageLoader() + ); _readContainer(reader, element, *menu); return menu; diff --git a/src/main.cpp b/src/main.cpp index b3623258..49825243 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,11 +21,15 @@ int main(int argc, char** argv) { debug::Logger::init(coreParameters.userFolder.string()+"/latest.log"); platform::configure_encoding(); + + auto& engine = Engine::getInstance(); try { - Engine(std::move(coreParameters)).run(); + engine.initialize(std::move(coreParameters)); + engine.run(); } catch (const initialize_error& err) { logger.error() << "could not to initialize engine\n" << err.what(); } + Engine::terminate(); #if defined(NDEBUG) and defined(_WIN32) catch (const std::exception& err) { logger.error() << "uncaught exception: " << err.what();