From 94e982289ebae7103c3aa0291144ceacd2f76612 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 3 Jun 2017 23:10:20 +0100 Subject: [PATCH] Fix openrct2-cli build By using a dummy audio context, we can now make openrct2-cli start a headless instance without any SDL2 calls. SDL2 is still a dependency until we remove out the input code to openrct2-ui. --- src/openrct2-cli/Cli.cpp | 17 ++++++-- src/openrct2-ui/Ui.cpp | 26 ++++++++---- src/openrct2/Context.cpp | 26 ++++++++++-- src/openrct2/Context.h | 2 + src/openrct2/audio/AudioContext.h | 2 + src/openrct2/audio/AudioMixer.cpp | 19 +++++---- src/openrct2/audio/DummyAudioContext.cpp | 52 ++++++++++++++++++++++++ src/openrct2/platform/shared.c | 20 +++++---- 8 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 src/openrct2/audio/DummyAudioContext.cpp diff --git a/src/openrct2-cli/Cli.cpp b/src/openrct2-cli/Cli.cpp index a71e09b77b..b43d5dbf61 100644 --- a/src/openrct2-cli/Cli.cpp +++ b/src/openrct2-cli/Cli.cpp @@ -15,6 +15,7 @@ #pragma endregion #include +#include using namespace OpenRCT2; @@ -23,8 +24,16 @@ using namespace OpenRCT2; */ int main(int argc, char * * argv) { - IContext * context = CreateContext(); - int exitCode = context->RunOpenRCT2(argc, argv); - delete context; - return exitCode; + core_init(); + int runGame = cmdline_run((const char * *)argv, argc); + if (runGame == 1) + { + gOpenRCT2Headless = true; + + // Run OpenRCT2 with a plain context + auto context = CreateContext(); + context->RunOpenRCT2(argc, argv); + delete context; + } + return gExitCode; } diff --git a/src/openrct2-ui/Ui.cpp b/src/openrct2-ui/Ui.cpp index c32f05b726..7d8fae6c3e 100644 --- a/src/openrct2-ui/Ui.cpp +++ b/src/openrct2-ui/Ui.cpp @@ -39,16 +39,26 @@ int main(int argc, char * * argv) int runGame = cmdline_run((const char * *)argv, argc); if (runGame == 1) { - // Run OpenRCT2 with a UI context - IAudioContext * audioContext = CreateAudioContext(); - IUiContext * uiContext = gOpenRCT2Headless ? CreateDummyUiContext() : CreateUiContext(); - IContext * context = CreateContext(audioContext, uiContext); + if (gOpenRCT2Headless) + { + // Run OpenRCT2 with a plain context + auto context = CreateContext(); + context->RunOpenRCT2(argc, argv); + delete context; + } + else + { + // Run OpenRCT2 with a UI context + auto audioContext = CreateAudioContext(); + auto uiContext = CreateUiContext(); + auto context = CreateContext(audioContext, uiContext); - context->RunOpenRCT2(argc, argv); + context->RunOpenRCT2(argc, argv); - delete context; - delete uiContext; - delete audioContext; + delete context; + delete uiContext; + delete audioContext; + } } return gExitCode; } diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 11c92ccc74..65e95c1d1e 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "audio/AudioContext.h" #include "Context.h" #include "ui/UiContext.h" #include "core/Console.hpp" @@ -139,8 +140,7 @@ namespace OpenRCT2 _finished = true; } - private: - bool Initialise() + bool Initialise() final override { #ifndef DISABLE_NETWORK gHashCTX = EVP_MD_CTX_create(); @@ -233,6 +233,7 @@ namespace OpenRCT2 return true; } + private: IPlatformEnvironment * SetupEnvironment() { utf8 userPath[MAX_PATH]; @@ -544,11 +545,30 @@ namespace OpenRCT2 } }; + class PlainContext final : public Context + { + std::unique_ptr _audioContext; + std::unique_ptr _uiContext; + + public: + PlainContext() + : PlainContext(CreateDummyAudioContext(), CreateDummyUiContext()) + { + } + + PlainContext(IAudioContext * audioContext, IUiContext * uiContext) + : Context(audioContext, uiContext) + { + _audioContext = std::unique_ptr(audioContext); + _uiContext = std::unique_ptr(uiContext); + } + }; + Context * Context::Instance = nullptr; IContext * CreateContext() { - return new Context(nullptr, nullptr); + return new PlainContext(); } IContext * CreateContext(Audio::IAudioContext * audioContext, IUiContext * uiContext) diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index 2aac65fce5..737732d647 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -80,6 +80,8 @@ namespace OpenRCT2 virtual Ui::IUiContext * GetUiContext() abstract; virtual sint32 RunOpenRCT2(int argc, char * * argv) abstract; + + virtual bool Initialise() abstract; virtual void Finish() abstract; }; diff --git a/src/openrct2/audio/AudioContext.h b/src/openrct2/audio/AudioContext.h index 31d77c7dd5..a917015ed7 100644 --- a/src/openrct2/audio/AudioContext.h +++ b/src/openrct2/audio/AudioContext.h @@ -60,5 +60,7 @@ namespace OpenRCT2 virtual void StopTitleMusic() abstract; virtual void StopVehicleSounds() abstract; }; + + IAudioContext * CreateDummyAudioContext(); } } diff --git a/src/openrct2/audio/AudioMixer.cpp b/src/openrct2/audio/AudioMixer.cpp index 41039b990f..e71eb64780 100644 --- a/src/openrct2/audio/AudioMixer.cpp +++ b/src/openrct2/audio/AudioMixer.cpp @@ -59,16 +59,19 @@ void * Mixer_Play_Effect(size_t id, sint32 loop, sint32 volume, float pan, doubl else { IAudioMixer * mixer = GetMixer(); - mixer->Lock(); - IAudioSource * source = mixer->GetSoundSource((sint32)id); - channel = mixer->Play(source, loop, deleteondone != 0, false); - if (channel != nullptr) + if (mixer != nullptr) { - channel->SetVolume(volume); - channel->SetPan(pan); - channel->SetRate(rate); + mixer->Lock(); + IAudioSource * source = mixer->GetSoundSource((sint32)id); + channel = mixer->Play(source, loop, deleteondone != 0, false); + if (channel != nullptr) + { + channel->SetVolume(volume); + channel->SetPan(pan); + channel->SetRate(rate); + } + mixer->Unlock(); } - mixer->Unlock(); } } return channel; diff --git a/src/openrct2/audio/DummyAudioContext.cpp b/src/openrct2/audio/DummyAudioContext.cpp new file mode 100644 index 0000000000..9ef86ca439 --- /dev/null +++ b/src/openrct2/audio/DummyAudioContext.cpp @@ -0,0 +1,52 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 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 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#include "AudioContext.h" + +namespace OpenRCT2 { namespace Audio +{ + class DummyAudioContext final : public IAudioContext + { + IAudioMixer * GetMixer() override { return nullptr; } + + std::vector GetOutputDevices() override { return std::vector(); } + void SetOutputDevice(const std::string &deviceName) override { } + + IAudioSource * CreateStreamFromWAV(const std::string &path) override { return nullptr; } + + void StartTitleMusic() override { } + + IAudioChannel * PlaySound(sint32 soundId, sint32 volume, sint32 pan) override { return nullptr; } + IAudioChannel * PlaySoundAtLocation(sint32 soundId, sint16 x, sint16 y, sint16 z) override { return nullptr; } + IAudioChannel * PlaySoundPanned(sint32 soundId, sint32 pan, sint16 x, sint16 y, sint16 z) override { return nullptr; } + + void ToggleAllSounds() override { } + void PauseSounds() override { } + void UnpauseSounds() override { } + + void StopAll() override { } + void StopCrowdSound() override { } + void StopRainSound() override { } + void StopRideMusic() override { } + void StopTitleMusic() override { } + void StopVehicleSounds() override { } + }; + + IAudioContext * CreateDummyAudioContext() + { + return new DummyAudioContext(); + } +} } diff --git a/src/openrct2/platform/shared.c b/src/openrct2/platform/shared.c index 8ee5e3047d..669f88da7b 100644 --- a/src/openrct2/platform/shared.c +++ b/src/openrct2/platform/shared.c @@ -210,13 +210,19 @@ uint8 platform_get_currency_value(const char *currCode) { void core_init() { - bitcount_init(); - + static bool initialised = false; + if (!initialised) + { + initialised = true; + + bitcount_init(); + #if defined(__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) - kern_return_t ret = mach_timebase_info(&_mach_base_info); - if (ret != 0) { - log_fatal("Unable to get mach_timebase_info."); - exit(-1); - } + kern_return_t ret = mach_timebase_info(&_mach_base_info); + if (ret != 0) { + log_fatal("Unable to get mach_timebase_info."); + exit(-1); + } #endif + } }