From 4b3ebf3e7e0c8f909d5202f923d7208f758164cf Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 5 Jan 2023 23:17:24 +0800 Subject: [PATCH] Add audio setup and shutdown to boot state --- CMakeLists.txt | 1 + src/application.cpp | 14 +++--- src/application.hpp | 11 ++-- src/game/context.hpp | 4 ++ src/game/state/boot.cpp | 109 +++++++++++++++++++++++++++++++++++----- src/game/state/boot.hpp | 18 ++++++- 6 files changed, 128 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a911884..e673fb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.7) + option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) diff --git a/src/application.cpp b/src/application.cpp index 26d24f3..7e52636 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -32,7 +32,7 @@ #include #include -application::application(): +application::application(debug::logger& log): closed(false), fullscreen(true), v_sync(false), @@ -42,27 +42,24 @@ application::application(): window_dimensions({0, 0}), viewport_dimensions({0, 0}), mouse_position({0, 0}), - logger(nullptr), + logger(&log), sdl_window(nullptr), sdl_gl_context(nullptr) { - // Setup logging - logger = new debug::logger(); - // Get SDL compiled version SDL_version sdl_compiled_version; SDL_VERSION(&sdl_compiled_version); std::string sdl_compiled_version_string = std::to_string(sdl_compiled_version.major) + "." + std::to_string(sdl_compiled_version.minor) + "." + std::to_string(sdl_compiled_version.patch); - logger->log("Compiled against SDL " + sdl_compiled_version_string); // Get SDL linked version SDL_version sdl_linked_version; SDL_GetVersion(&sdl_linked_version); std::string sdl_linked_version_string = std::to_string(sdl_linked_version.major) + "." + std::to_string(sdl_linked_version.minor) + "." + std::to_string(sdl_linked_version.patch); - logger->log("Linking against SDL " + sdl_linked_version_string); // Init SDL logger->push_task("Initializing SDL"); + logger->log("Compiled against SDL " + sdl_compiled_version_string); + logger->log("Linking against SDL " + sdl_linked_version_string); if (SDL_Init(SDL_INIT_VIDEO) != 0) { logger->pop_task(EXIT_FAILURE); @@ -72,6 +69,7 @@ application::application(): { logger->pop_task(EXIT_SUCCESS); } + // Load default OpenGL library logger->push_task("Loading OpenGL library"); if (SDL_GL_LoadLibrary(nullptr) != 0) @@ -353,7 +351,7 @@ void application::hide_window() void application::add_game_controller_mappings(const void* mappings, std::size_t size) { logger->push_task("Adding SDL game controller mappings"); - int mapping_count = SDL_GameControllerAddMappingsFromRW(SDL_RWFromConstMem(mappings, size), 0); + int mapping_count = SDL_GameControllerAddMappingsFromRW(SDL_RWFromConstMem(mappings, static_cast(size)), 0); if (mapping_count == -1) { logger->pop_task(EXIT_FAILURE); diff --git a/src/application.hpp b/src/application.hpp index 8b94a65..537fedf 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -28,18 +28,13 @@ #include "input/mouse.hpp" #include "input/gamepad.hpp" #include "utility/fundamental-types.hpp" +#include "debug/logger.hpp" // Forward declarations typedef struct SDL_Window SDL_Window; typedef void* SDL_GLContext; class event_dispatcher; -namespace debug -{ - class logger; - class performance_sampler; -} - /** * */ @@ -48,8 +43,10 @@ class application public: /** * Creates and initializes an application. + * + * @param logger Debug logger. */ - application(); + application(debug::logger& log); /** * Destroys an application. diff --git a/src/game/context.hpp b/src/game/context.hpp index 539d8a2..b46e338 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -58,6 +58,8 @@ #include "state-machine.hpp" #include "debug/performance-sampler.hpp" #include +#include +#include // Forward declarations class animator; @@ -262,6 +264,8 @@ struct context animation* camera_flash_animation; // Sound + ALCdevice* alc_device; + ALCcontext* alc_context; float master_volume; float ambience_volume; float effects_volume; diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index 45671f5..07dfd80 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -107,24 +107,25 @@ namespace state { boot::boot(game::context& ctx, int argc, char** argv): game::state::base(ctx) { - // Allocate application - ctx.app = new application(); - - // Get application logger - ctx.logger = ctx.app->get_logger(); + // Allocate application logger + ctx.logger = new debug::logger(); // Boot process - ctx.logger->push_task("Entering boot state"); + ctx.logger->push_task("Booting up"); try { + // Allocate application + ctx.app = new application(*ctx.logger); + // Parse command line options parse_options(argc, argv); + setup_resources(); load_config(); load_strings(); setup_window(); setup_rendering(); - setup_sound(); + setup_audio(); setup_scenes(); setup_animation(); setup_entities(); @@ -152,11 +153,22 @@ boot::boot(game::context& ctx, int argc, char** argv): boot::~boot() { - ctx.logger->push_task("Exiting boot state"); + ctx.logger->push_task("Booting down"); - // Close application - delete ctx.app; - ctx.app = nullptr; + try + { + shutdown_audio(); + + // Close application + delete ctx.app; + ctx.app = nullptr; + } + catch (const std::exception& e) + { + ctx.logger->error("Caught exception: \"" + std::string(e.what()) + "\""); + ctx.logger->pop_task(EXIT_FAILURE); + return; + } ctx.logger->pop_task(EXIT_SUCCESS); } @@ -583,10 +595,10 @@ void boot::setup_rendering() logger->pop_task(EXIT_SUCCESS); } -void boot::setup_sound() +void boot::setup_audio() { debug::logger* logger = ctx.logger; - logger->push_task("Setting up sound"); + logger->push_task("Setting up audio"); // Load master volume config ctx.master_volume = 1.0f; @@ -618,6 +630,59 @@ void boot::setup_sound() if (ctx.config->contains("captions_size")) ctx.captions_size = (*ctx.config)["captions_size"].get(); + // Open audio device + logger->push_task("Opening audio device"); + ctx.alc_device = alcOpenDevice(nullptr); + if (!ctx.alc_device) + { + logger->pop_task(EXIT_FAILURE); + return; + } + else + { + // Get audio device name + const ALCchar* alc_device_name = nullptr; + if (alcIsExtensionPresent(ctx.alc_device, "ALC_ENUMERATE_ALL_EXT")) + alc_device_name = alcGetString(ctx.alc_device, ALC_ALL_DEVICES_SPECIFIER); + if (alcGetError(ctx.alc_device) != AL_NO_ERROR || !alc_device_name) + alc_device_name = alcGetString(ctx.alc_device, ALC_DEVICE_SPECIFIER); + + logger->log("Opened audio device \"" + std::string(alc_device_name) + "\""); + + logger->pop_task(EXIT_SUCCESS); + } + + // Create audio context + logger->push_task("Creating audio context"); + ctx.alc_context = alcCreateContext(ctx.alc_device, nullptr); + if (!ctx.alc_context) + { + logger->pop_task(EXIT_FAILURE); + alcCloseDevice(ctx.alc_device); + return; + } + else + { + logger->pop_task(EXIT_SUCCESS); + } + + // Make audio context current + logger->push_task("Making audio context current"); + if (alcMakeContextCurrent(ctx.alc_context) == ALC_FALSE) + { + logger->pop_task(EXIT_FAILURE); + if (ctx.alc_context != nullptr) + { + alcDestroyContext(ctx.alc_context); + } + alcCloseDevice(ctx.alc_device); + return; + } + else + { + logger->pop_task(EXIT_SUCCESS); + } + logger->pop_task(EXIT_SUCCESS); } @@ -1171,5 +1236,23 @@ void boot::loop() ctx.state_machine.pop(); } +void boot::shutdown_audio() +{ + ctx.logger->push_task("Shutting down audio"); + + if (ctx.alc_context) + { + alcMakeContextCurrent(nullptr); + alcDestroyContext(ctx.alc_context); + } + + if (ctx.alc_device) + { + alcCloseDevice(ctx.alc_device); + } + + ctx.logger->pop_task(EXIT_SUCCESS); +} + } // namespace state } // namespace game diff --git a/src/game/state/boot.hpp b/src/game/state/boot.hpp index 419a62c..a183ec5 100644 --- a/src/game/state/boot.hpp +++ b/src/game/state/boot.hpp @@ -27,10 +27,24 @@ namespace game { namespace state { +/** + * Boots the game up on construction, and down on destruction. + */ class boot: public game::state::base { public: + /** + * Boots up the game. + * + * @param ctx Game context. + * @param argc Command line argument count. + * @param argv Command line argument vector. + */ boot(game::context& ctx, int argc, char** argv); + + /** + * Boots down the game. + */ virtual ~boot(); private: @@ -40,7 +54,7 @@ private: void load_strings(); void setup_window(); void setup_rendering(); - void setup_sound(); + void setup_audio(); void setup_scenes(); void setup_animation(); void setup_entities(); @@ -51,6 +65,8 @@ private: void setup_loop(); void loop(); + void shutdown_audio(); + // Command line options std::optional option_continue; std::optional option_data;