Large refactoring to improve thread safety and improve singleton pattern usage.

This commit is contained in:
Leon Styhre 2022-01-04 21:21:26 +01:00
parent 51bb48b603
commit 254b00a3d8
57 changed files with 267 additions and 359 deletions

View file

@ -43,12 +43,8 @@ std::string myCollectionsName = "collections";
#define LAST_PLAYED_MAX 50
// Handles the getting, initialization, deinitialization,
// saving and deletion of a CollectionSystemsManager instance.
CollectionSystemsManager* CollectionSystemsManager::sInstance = nullptr;
CollectionSystemsManager::CollectionSystemsManager(Window* window)
: mWindow(window)
CollectionSystemsManager::CollectionSystemsManager() noexcept
: mWindow(Window::getInstance())
{
// clang-format off
CollectionSystemDecl systemDecls[] = {
@ -92,8 +88,6 @@ CollectionSystemsManager::CollectionSystemsManager(Window* window)
CollectionSystemsManager::~CollectionSystemsManager()
{
assert(sInstance == this);
// Don't attempt to remove any collections if no systems exist.
if (SystemData::sSystemVector.size() > 0)
removeCollectionsFromDisplayedSystems();
@ -114,25 +108,12 @@ CollectionSystemsManager::~CollectionSystemsManager()
delete (*it).second.system;
delete mCollectionEnvData;
sInstance = nullptr;
}
CollectionSystemsManager* CollectionSystemsManager::get()
CollectionSystemsManager* CollectionSystemsManager::getInstance()
{
assert(sInstance);
return sInstance;
}
void CollectionSystemsManager::init(Window* window)
{
assert(!sInstance);
sInstance = new CollectionSystemsManager(window);
}
void CollectionSystemsManager::deinit()
{
if (sInstance)
delete sInstance;
static CollectionSystemsManager instance;
return &instance;
}
void CollectionSystemsManager::saveCustomCollection(SystemData* sys)
@ -927,8 +908,8 @@ void CollectionSystemsManager::deleteCustomCollection(const std::string& collect
delete mWindow->peekGui();
if (collectionEntry != mCustomCollectionSystemsData.end()) {
CollectionSystemsManager::get()->loadEnabledListFromSettings();
CollectionSystemsManager::get()->updateSystemsList();
CollectionSystemsManager::getInstance()->loadEnabledListFromSettings();
CollectionSystemsManager::getInstance()->updateSystemsList();
ViewController::get()->removeGameListView(collectionEntry->second.system);
ViewController::get()->reloadAll();

View file

@ -72,12 +72,7 @@ struct stringComparator {
class CollectionSystemsManager
{
public:
CollectionSystemsManager(Window* window);
~CollectionSystemsManager();
static CollectionSystemsManager* get();
static void init(Window* window);
static void deinit();
static CollectionSystemsManager* getInstance();
void saveCustomCollection(SystemData* sys);
// Functions to load all collections into memory, and enable the active ones:
@ -137,7 +132,9 @@ public:
const std::string& getEditingCollection() const { return mEditingCollection; }
private:
static CollectionSystemsManager* sInstance;
CollectionSystemsManager() noexcept;
~CollectionSystemsManager();
SystemEnvironmentData* mCollectionEnvData;
std::map<std::string, CollectionSystemDecl, stringComparator> mCollectionSystemDeclsIndex;
std::map<std::string, CollectionSystemData, stringComparator> mAutoCollectionSystemsData;

View file

@ -1166,7 +1166,7 @@ void FileData::launchGame(Window* window)
gameToUpdate->metadata.get("lastplayed"));
}
CollectionSystemsManager::get()->refreshCollectionSystems(gameToUpdate);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(gameToUpdate);
gameToUpdate->mSystem->onMetaDataSavePoint();
}

View file

@ -12,8 +12,8 @@
#include "components/VideoFFmpegComponent.h"
#include "views/ViewController.h"
MediaViewer::MediaViewer(Window* window)
: mWindow(window)
MediaViewer::MediaViewer()
: mWindow(Window::getInstance())
, mVideo(nullptr)
, mImage(nullptr)
{

View file

@ -17,7 +17,7 @@
class MediaViewer : public Window::MediaViewer
{
public:
MediaViewer(Window* window);
MediaViewer();
virtual ~MediaViewer();
virtual bool startMediaViewer(FileData* game) override;

View file

@ -51,14 +51,14 @@ void FindRules::loadFindRules()
}
else {
#if defined(_WIN64)
path = ResourceManager::getInstance()->getResourcePath(
":/systems/windows/es_find_rules.xml", false);
path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_find_rules.xml",
false);
#elif defined(__APPLE__)
path = ResourceManager::getInstance()->getResourcePath(":/systems/macos/es_find_rules.xml",
false);
path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_find_rules.xml",
false);
#else
path = ResourceManager::getInstance()->getResourcePath(":/systems/unix/es_find_rules.xml",
false);
path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml",
false);
#endif
}
@ -659,7 +659,7 @@ bool SystemData::loadConfig()
// Don't load any collections if there are no systems available.
if (sSystemVector.size() > 0)
CollectionSystemsManager::get()->loadCollectionSystems();
CollectionSystemsManager::getInstance()->loadCollectionSystems();
return false;
}
@ -718,12 +718,11 @@ std::vector<std::string> SystemData::getConfigPath(bool legacyWarning)
}
#if defined(_WIN64)
path =
ResourceManager::getInstance()->getResourcePath(":/systems/windows/es_systems.xml", true);
path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true);
#elif defined(__APPLE__)
path = ResourceManager::getInstance()->getResourcePath(":/systems/macos/es_systems.xml", true);
path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true);
#else
path = ResourceManager::getInstance()->getResourcePath(":/systems/unix/es_systems.xml", true);
path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_systems.xml", true);
#endif
paths.push_back(path);

View file

@ -29,8 +29,8 @@
#define FADE_TIME 300
SystemScreensaver::SystemScreensaver(Window* window)
: mWindow(window)
SystemScreensaver::SystemScreensaver()
: mWindow(Window::getInstance())
, mState(STATE_INACTIVE)
, mImageScreensaver(nullptr)
, mVideoScreensaver(nullptr)

View file

@ -19,7 +19,7 @@ class VideoComponent;
class SystemScreensaver : public Window::Screensaver
{
public:
SystemScreensaver(Window* window);
SystemScreensaver();
virtual ~SystemScreensaver();
virtual bool allowSleep()

View file

@ -20,8 +20,6 @@ std::string VolumeControl::mixerName = "Master";
std::string VolumeControl::mixerCard = "default";
#endif
VolumeControl* VolumeControl::sInstance = nullptr;
VolumeControl::VolumeControl()
#if defined(__linux__)
: mixerIndex(0)
@ -44,23 +42,6 @@ VolumeControl::~VolumeControl()
#endif
}
VolumeControl* VolumeControl::getInstance()
{
// Check if a VolumeControl instance is already created, and if not then create it.
if (!sInstance)
sInstance = new VolumeControl();
return sInstance;
}
void VolumeControl::deleteInstance()
{
if (sInstance) {
delete sInstance;
sInstance = nullptr;
}
}
void VolumeControl::init()
{
// Initialize audio mixer interface.

View file

@ -27,17 +27,12 @@ public:
VolumeControl();
~VolumeControl();
static VolumeControl* getInstance();
void deleteInstance();
void init();
void deinit();
int getVolume() const;
void setVolume(int volume);
static VolumeControl* sInstance;
#if defined(__linux__)
static std::string mixerName;
static std::string mixerCard;

View file

@ -25,18 +25,19 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
, mDeletedCustomCollection(false)
{
// Finish editing custom collection.
if (CollectionSystemsManager::get()->isEditing()) {
if (CollectionSystemsManager::getInstance()->isEditing()) {
ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(
mWindow,
"FINISH EDITING '" +
Utils::String::toUpper(
CollectionSystemsManager::get()->getEditingCollection()) +
"' COLLECTION",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
true);
row.addElement(
std::make_shared<TextComponent>(
mWindow,
"FINISH EDITING '" +
Utils::String::toUpper(
CollectionSystemsManager::getInstance()->getEditingCollection()) +
"' COLLECTION",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
true);
row.makeAcceptInputHandler([this] {
CollectionSystemsManager::get()->exitEditMode();
CollectionSystemsManager::getInstance()->exitEditMode();
mWindow->invalidateCachedBackground();
delete this;
});
@ -47,7 +48,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
collection_systems_auto = std::make_shared<OptionListComponent<std::string>>(
mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
std::map<std::string, CollectionSystemData, stringComparator> autoSystems =
CollectionSystemsManager::get()->getAutoCollectionSystems();
CollectionSystemsManager::getInstance()->getAutoCollectionSystems();
// Add automatic systems.
for (std::map<std::string, CollectionSystemData, stringComparator>::const_iterator it =
autoSystems.cbegin();
@ -60,8 +61,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
collection_systems_auto->getSelectedObjects(), ",", true);
std::string autoSystemsConfig = Settings::getInstance()->getString("CollectionSystemsAuto");
if (autoSystemsSelected != autoSystemsConfig) {
if (CollectionSystemsManager::get()->isEditing())
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing())
CollectionSystemsManager::getInstance()->exitEditMode();
Settings::getInstance()->setString("CollectionSystemsAuto", autoSystemsSelected);
// Check if any systems have been enabled, and if so repopulate them, which results in
// a complete initialization of their content. This is necessary as collections aren't
@ -83,7 +84,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
}
if (!addedAutoSystems.empty()) {
for (std::string system : addedAutoSystems)
CollectionSystemsManager::get()->repopulateCollection(
CollectionSystemsManager::getInstance()->repopulateCollection(
autoSystems.find(system)->second.system);
}
setNeedsSaving();
@ -96,7 +97,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
collection_systems_custom = std::make_shared<OptionListComponent<std::string>>(
mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
std::map<std::string, CollectionSystemData, stringComparator> customSystems =
CollectionSystemsManager::get()->getCustomCollectionSystems();
CollectionSystemsManager::getInstance()->getCustomCollectionSystems();
// Add custom systems.
for (std::map<std::string, CollectionSystemData, stringComparator>::const_iterator it =
customSystems.cbegin();
@ -112,8 +113,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
std::string customSystemsConfig =
Settings::getInstance()->getString("CollectionSystemsCustom");
if (customSystemsSelected != customSystemsConfig) {
if (CollectionSystemsManager::get()->isEditing())
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing())
CollectionSystemsManager::getInstance()->exitEditMode();
Settings::getInstance()->setString("CollectionSystemsCustom",
customSystemsSelected);
// Check if any systems have been enabled, and if so repopulate them, which
@ -137,7 +138,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
}
if (!mAddedCustomCollection && !addedCustomSystems.empty()) {
for (std::string system : addedCustomSystems)
CollectionSystemsManager::get()->repopulateCollection(
CollectionSystemsManager::getInstance()->repopulateCollection(
customSystems.find(system)->second.system);
}
setNeedsSaving();
@ -159,7 +160,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
// Create custom collection from theme.
std::vector<std::string> unusedFolders =
CollectionSystemsManager::get()->getUnusedSystemsFromTheme();
CollectionSystemsManager::getInstance()->getUnusedSystemsFromTheme();
if (unusedFolders.size() > 0) {
ComponentListRow row;
auto themeCollection =
@ -259,8 +260,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
"ARE YOU SURE?",
"YES",
[this, name] {
if (CollectionSystemsManager::get()->isEditing())
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing())
CollectionSystemsManager::getInstance()->exitEditMode();
mDeletedCustomCollection = true;
std::vector<std::string> selectedCustomCollections =
collection_systems_custom->getSelectedObjects();
@ -289,7 +290,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
setNeedsSaving();
setNeedsGoToStart();
}
CollectionSystemsManager::get()->deleteCustomCollection(name);
CollectionSystemsManager::getInstance()->deleteCustomCollection(name);
return true;
},
"NO", [] { return false; }));
@ -349,8 +350,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
Settings::getInstance()->getBool("UseCustomCollectionsSystem")) {
Settings::getInstance()->setBool("UseCustomCollectionsSystem",
use_custom_collections_system->getState());
if (CollectionSystemsManager::get()->isEditing())
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing())
CollectionSystemsManager::getInstance()->exitEditMode();
setNeedsSaving();
setNeedsCollectionsUpdate();
setNeedsReloading();
@ -378,14 +379,15 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
void GuiCollectionSystemsOptions::createCustomCollection(std::string inName)
{
if (CollectionSystemsManager::get()->isEditing())
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing())
CollectionSystemsManager::getInstance()->exitEditMode();
std::string collectionName = CollectionSystemsManager::get()->getValidNewCollectionName(inName);
std::string collectionName =
CollectionSystemsManager::getInstance()->getValidNewCollectionName(inName);
SystemData* newCollection =
CollectionSystemsManager::get()->addNewCustomCollection(collectionName);
CollectionSystemsManager::getInstance()->addNewCustomCollection(collectionName);
CollectionSystemsManager::get()->saveCustomCollection(newCollection);
CollectionSystemsManager::getInstance()->saveCustomCollection(newCollection);
collection_systems_custom->add(collectionName, collectionName, true);
mAddedCustomCollection = true;
@ -399,5 +401,5 @@ void GuiCollectionSystemsOptions::createCustomCollection(std::string inName)
Window* window = mWindow;
while (window->peekGui() && window->peekGui() != ViewController::get())
delete window->peekGui();
CollectionSystemsManager::get()->setEditMode(collectionName);
CollectionSystemsManager::getInstance()->setEditMode(collectionName);
}

View file

@ -161,7 +161,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system)
}
}
// Add a dummy entry when applicable as the menu looks quite ugly if it's just blank.
else if (!CollectionSystemsManager::get()->isEditing() &&
else if (!CollectionSystemsManager::getInstance()->isEditing() &&
mSystem->getRootFolder()->getChildren().size() == 0 && !mIsCustomCollectionGroup &&
!mIsCustomCollection) {
row.elements.clear();
@ -179,7 +179,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system)
if (UIModeController::getInstance()->isUIModeFull() &&
(mIsCustomCollection || mIsCustomCollectionGroup)) {
if (CollectionSystemsManager::get()->getEditingCollection() != customSystem) {
if (CollectionSystemsManager::getInstance()->getEditingCollection() != customSystem) {
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow,
"ADD/REMOVE GAMES TO THIS COLLECTION",
@ -191,16 +191,17 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system)
}
if (UIModeController::getInstance()->isUIModeFull() &&
CollectionSystemsManager::get()->isEditing()) {
CollectionSystemsManager::getInstance()->isEditing()) {
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(
mWindow,
"FINISH EDITING '" +
Utils::String::toUpper(
CollectionSystemsManager::get()->getEditingCollection()) +
"' COLLECTION",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
true);
row.addElement(
std::make_shared<TextComponent>(
mWindow,
"FINISH EDITING '" +
Utils::String::toUpper(
CollectionSystemsManager::getInstance()->getEditingCollection()) +
"' COLLECTION",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
true);
row.makeAcceptInputHandler(std::bind(&GuiGamelistOptions::exitEditMode, this));
mMenu.addRow(row);
}
@ -336,7 +337,8 @@ void GuiGamelistOptions::startEditMode()
std::string editingSystem = mSystem->getName();
// Need to check if we're editing the collections bundle,
// as we will want to edit the selected collection within.
if (editingSystem == CollectionSystemsManager::get()->getCustomCollectionsBundle()->getName()) {
if (editingSystem ==
CollectionSystemsManager::getInstance()->getCustomCollectionsBundle()->getName()) {
FileData* file = getGamelist()->getCursor();
// Do we have the cursor on a specific collection?.
if (file->getType() == FOLDER)
@ -345,7 +347,7 @@ void GuiGamelistOptions::startEditMode()
// We are inside a specific collection. We want to edit that one.
editingSystem = file->getSystem()->getName();
}
CollectionSystemsManager::get()->setEditMode(editingSystem);
CollectionSystemsManager::getInstance()->setEditMode(editingSystem);
// Display the indication icons which show what games are part of the custom collection
// currently being edited. This is done cheaply using onFileChanged() which will trigger
@ -362,7 +364,7 @@ void GuiGamelistOptions::startEditMode()
void GuiGamelistOptions::exitEditMode()
{
CollectionSystemsManager::get()->exitEditMode();
CollectionSystemsManager::getInstance()->exitEditMode();
if (mSystem->getRootFolder()->getChildren().size() == 0)
NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND);
delete this;
@ -420,7 +422,7 @@ void GuiGamelistOptions::openMetaDataEd()
// Update all collections where the game is present.
if (file->getType() == GAME)
CollectionSystemsManager::get()->refreshCollectionSystems(file, true);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(file, true);
file->getSystem()->sortSystem();
// This delay reduces the likelyhood that the SVG rasterizer which is running in a
@ -440,7 +442,7 @@ void GuiGamelistOptions::openMetaDataEd()
deleteGameBtnFunc = [this, file] {
LOG(LogInfo) << "Deleting the game file \"" << file->getFullPath()
<< "\", all its media files and its gamelist.xml entry.";
CollectionSystemsManager::get()->deleteCollectionFiles(file);
CollectionSystemsManager::getInstance()->deleteCollectionFiles(file);
ViewController::get()->getGameListView(file->getSystem()).get()->removeMedia(file);
ViewController::get()->getGameListView(file->getSystem()).get()->remove(file, true);
mSystem->getRootFolder()->sort(*mListSort->getSelected(), mFavoritesSorting);
@ -551,7 +553,7 @@ std::vector<HelpPrompt> GuiGamelistOptions::getHelpPrompts()
{
auto prompts = mMenu.getHelpPrompts();
if (mSystem->getRootFolder()->getChildren().size() > 0 || mIsCustomCollectionGroup ||
mIsCustomCollection || CollectionSystemsManager::get()->isEditing())
mIsCustomCollection || CollectionSystemsManager::getInstance()->isEditing())
prompts.push_back(HelpPrompt("a", "select"));
if (mSystem->getRootFolder()->getChildren().size() > 0 && mSystem->getName() != "recent") {
prompts.push_back(HelpPrompt("b", "close (apply)"));

View file

@ -14,10 +14,10 @@
#include "components/TextComponent.h"
#include "utils/StringUtil.h"
GuiLaunchScreen::GuiLaunchScreen(Window* window)
: GuiComponent(window)
, mWindow(window)
, mBackground(window, ":/graphics/frame.svg")
GuiLaunchScreen::GuiLaunchScreen()
: GuiComponent(Window::getInstance())
, mWindow(Window::getInstance())
, mBackground(mWindow, ":/graphics/frame.svg")
, mGrid(nullptr)
, mMarquee(nullptr)
{

View file

@ -21,7 +21,7 @@ class FileData;
class GuiLaunchScreen : public Window::GuiLaunchScreen, GuiComponent
{
public:
GuiLaunchScreen(Window* window);
GuiLaunchScreen();
virtual ~GuiLaunchScreen();
virtual void displayLaunchScreen(FileData* game) override;

View file

@ -189,12 +189,12 @@ void GuiMenu::openUIOptions()
Scripting::fireEvent("theme-changed", theme_set->getSelected(),
Settings::getInstance()->getString("ThemeSet"));
Settings::getInstance()->setString("ThemeSet", theme_set->getSelected());
CollectionSystemsManager::get()->updateSystemsList();
CollectionSystemsManager::getInstance()->updateSystemsList();
mWindow->setChangedThemeSet();
// This is required so that the custom collection system does not disappear
// if the user is editing a custom collection when switching theme sets.
if (CollectionSystemsManager::get()->isEditing()) {
CollectionSystemsManager::get()->exitEditMode();
if (CollectionSystemsManager::getInstance()->isEditing()) {
CollectionSystemsManager::getInstance()->exitEditMode();
s->setNeedsCollectionsUpdate();
}
s->setNeedsSaving();
@ -609,16 +609,22 @@ void GuiMenu::openSoundOptions()
// implemented for these operating systems.
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
// System volume.
auto system_volume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
system_volume->setValue(static_cast<float>(VolumeControl::getInstance()->getVolume()));
s->addWithLabel("SYSTEM VOLUME", system_volume);
s->addSaveFunc([system_volume] {
VolumeControl::getInstance()->setVolume(
static_cast<int>(std::round(system_volume->getValue())));
// Explicitly delete the VolumeControl instance so that it will reinitialize the
// next time the menu is entered. This is the easiest way to detect new default
// audio devices or changes to the audio volume done by the operating system.
VolumeControl::getInstance()->deleteInstance();
// The reason to create the VolumeControl object every time instead of making it a singleton
// is that this is the easiest way to detect new default audio devices or changes to the
// audio volume done by the operating system. And we don't really need this object laying
// around anyway as it's only used here.
VolumeControl volumeControl;
int currentVolume = volumeControl.getVolume();
auto systemVolume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
systemVolume->setValue(static_cast<float>(currentVolume));
s->addWithLabel("SYSTEM VOLUME", systemVolume);
s->addSaveFunc([systemVolume, currentVolume] {
// No need to create the VolumeControl object unless the volume has actually been changed.
if (static_cast<int>(systemVolume->getValue()) != currentVolume) {
VolumeControl volumeControl;
volumeControl.setVolume(static_cast<int>(std::round(systemVolume->getValue())));
}
});
#endif

View file

@ -689,7 +689,7 @@ void GuiMetaDataEd::save()
// Update disabled auto collections when hiding a game, as otherwise these could
// get invalid gamelist cursor positions. A cursor pointing to a removed game
// would crash the application upon enabling the collections.
CollectionSystemsManager::get()->refreshCollectionSystems(hideGame, true);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(hideGame, true);
// Remove the game from the index of all systems.
for (SystemData* sys : SystemData::sSystemVector) {
std::vector<FileData*> children;
@ -706,13 +706,14 @@ void GuiMetaDataEd::save()
}
else {
// Update all collections where the game is present.
CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(mScraperParams.game);
}
// If game counting was re-enabled for the game, then reactivate it in any custom collections
// where it may exist.
if (setGameAsCounted)
CollectionSystemsManager::get()->reactivateCustomCollectionEntry(mScraperParams.game);
CollectionSystemsManager::getInstance()->reactivateCustomCollectionEntry(
mScraperParams.game);
mScraperParams.system->onMetaDataSavePoint();
@ -812,7 +813,7 @@ void GuiMetaDataEd::close()
TextureResource::manualUnload(mScraperParams.game->getMarqueePath(), false);
ViewController::get()->reloadGameListView(mScraperParams.system);
// Update all collections where the game is present.
CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(mScraperParams.game);
mWindow->invalidateCachedBackground();
}
ViewController::get()->onPauseVideo();

View file

@ -280,7 +280,7 @@ void GuiScraperMulti::acceptResult(const ScraperSearchResult& result)
mSearchQueue.pop();
++mCurrentGame;
++mTotalSuccessful;
CollectionSystemsManager::get()->refreshCollectionSystems(search.game);
CollectionSystemsManager::getInstance()->refreshCollectionSystems(search.game);
doNextSearch();
}

View file

@ -66,8 +66,8 @@ void GuiSettings::save()
mWindow->reloadHelpPrompts();
if (mNeedsCollectionsUpdate) {
CollectionSystemsManager::get()->loadEnabledListFromSettings();
CollectionSystemsManager::get()->updateSystemsList();
CollectionSystemsManager::getInstance()->loadEnabledListFromSettings();
CollectionSystemsManager::getInstance()->updateSystemsList();
}
if (mNeedsSorting) {

View file

@ -528,24 +528,27 @@ int main(int argc, char* argv[])
}
}
Window window;
SystemScreensaver screensaver(&window);
MediaViewer mediaViewer(&window);
GuiLaunchScreen guiLaunchScreen(&window);
ViewController::init(&window);
CollectionSystemsManager::init(&window);
window.pushGui(ViewController::get());
Window* window = Window::getInstance();
ViewController::get();
CollectionSystemsManager::getInstance();
SystemScreensaver screensaver;
MediaViewer mediaViewer;
GuiLaunchScreen guiLaunchScreen;
if (!window->init()) {
LOG(LogError) << "Window failed to initialize";
return 1;
}
window->pushGui(ViewController::get());
bool splashScreen = Settings::getInstance()->getBool("SplashScreen");
bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress");
SDL_Event event{};
if (!window.init()) {
LOG(LogError) << "Window failed to initialize";
return 1;
}
InputManager::getInstance()->parseEvent(event, &window);
InputManager::getInstance().parseEvent(event, window);
if (event.type == SDL_QUIT)
return 1;
@ -571,7 +574,7 @@ int main(int argc, char* argv[])
std::string progressText = "Loading...";
if (splashScreenProgress)
progressText = "Loading system config...";
window.renderLoadingScreen(progressText);
window->renderLoadingScreen(progressText);
}
AudioManager::getInstance();
@ -609,13 +612,13 @@ int main(int argc, char* argv[])
ViewController::get()->preload();
if (splashScreen && splashScreenProgress)
window.renderLoadingScreen("Done");
window->renderLoadingScreen("Done");
// Open the input configuration GUI if the flag to force this was passed from the command line.
if (!loadSystemsStatus) {
if (forceInputConfig) {
window.pushGui(new GuiDetectDevice(&window, false, true,
[] { ViewController::get()->goToStart(true); }));
window->pushGui(new GuiDetectDevice(window, false, true,
[] { ViewController::get()->goToStart(true); }));
}
else {
ViewController::get()->goToStart(true);
@ -645,7 +648,7 @@ int main(int argc, char* argv[])
while (running) {
if (SDL_PollEvent(&event)) {
do {
InputManager::getInstance()->parseEvent(event, &window);
InputManager::getInstance().parseEvent(event, window);
if (event.type == SDL_QUIT)
running = false;
@ -653,7 +656,7 @@ int main(int argc, char* argv[])
} while (SDL_PollEvent(&event));
}
if (window.isSleeping()) {
if (window->isSleeping()) {
lastTime = SDL_GetTicks();
// This doesn't need to be accurate, we're just giving up
// our CPU time until something wakes us up.
@ -669,18 +672,17 @@ int main(int argc, char* argv[])
if (deltaTime < 0)
deltaTime = 1000;
window.update(deltaTime);
window.render();
window->update(deltaTime);
window->render();
Renderer::swapBuffers();
Log::flush();
}
while (window.peekGui() != ViewController::get())
delete window.peekGui();
window.deinit();
while (window->peekGui() != ViewController::get())
delete window->peekGui();
window->deinit();
CollectionSystemsManager::deinit();
SystemData::deleteSystems();
NavigationSounds::getInstance().deinit();

View file

@ -77,9 +77,9 @@ void SystemView::populate()
auto path = logoElem->get<std::string>("path");
std::string defaultPath =
logoElem->has("default") ? logoElem->get<std::string>("default") : "";
if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) ||
if ((!path.empty() && ResourceManager::getInstance().fileExists(path)) ||
(!defaultPath.empty() &&
ResourceManager::getInstance()->fileExists(defaultPath))) {
ResourceManager::getInstance().fileExists(defaultPath))) {
auto* logo = new ImageComponent(mWindow, false, false);
logo->setMaxSize(glm::round(mCarousel.logoSize * mCarousel.logoScale));
logo->applyTheme(theme, "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
@ -101,9 +101,9 @@ void SystemView::populate()
auto path = logoElem->get<std::string>("path");
std::string defaultPath =
logoElem->has("default") ? logoElem->get<std::string>("default") : "";
if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) ||
if ((!path.empty() && ResourceManager::getInstance().fileExists(path)) ||
(!defaultPath.empty() &&
ResourceManager::getInstance()->fileExists(defaultPath))) {
ResourceManager::getInstance().fileExists(defaultPath))) {
auto* logo = new ImageComponent(mWindow, false, false);
logo->applyTheme(theme, "system", "logoPlaceholderImage", ThemeFlags::ALL);
if (!logoElem->has("size"))

View file

@ -16,25 +16,7 @@
#include "utils/StringUtil.h"
#include "views/ViewController.h"
UIModeController* UIModeController::sInstance = nullptr;
UIModeController* UIModeController::getInstance()
{
if (sInstance == nullptr)
sInstance = new UIModeController();
return sInstance;
}
void UIModeController::deinit()
{
if (sInstance) {
delete sInstance;
sInstance = nullptr;
}
}
UIModeController::UIModeController()
UIModeController::UIModeController() noexcept
: mPassKeyCounter(0)
{
mPassKeySequence = Settings::getInstance()->getString("UIMode_passkey");
@ -47,6 +29,12 @@ UIModeController::UIModeController()
}
}
UIModeController* UIModeController::getInstance()
{
static UIModeController instance;
return &instance;
}
void UIModeController::monitorUIMode()
{
std::string uimode = Settings::getInstance()->getString("UIMode");

View file

@ -23,7 +23,6 @@ class UIModeController
{
public:
static UIModeController* getInstance();
static void deinit();
// Monitor input for UI mode change, returns true (consumes input) when a UI mode
// change is triggered.
@ -42,15 +41,14 @@ public:
void setCurrentUIMode(const std::string& mode) { mCurrentUIMode = mode; }
private:
UIModeController();
UIModeController() noexcept;
bool inputIsMatch(InputConfig* config, Input input);
bool isValidInput(InputConfig* config, Input input);
// Return UI mode to 'full'.
void unlockUIMode();
static UIModeController* sInstance;
// Default passkeyseq = "uuddlrlrba", as defined in the setting 'UIMode_passkey'.
std::string mPassKeySequence;

View file

@ -33,8 +33,6 @@
#include "views/gamelist/IGameListView.h"
#include "views/gamelist/VideoGameListView.h"
ViewController* ViewController::sInstance = nullptr;
#if defined(_MSC_VER) // MSVC compiler.
const std::string ViewController::CONTROLLER_CHAR = Utils::String::wideStringToString(L"\uf11b");
const std::string ViewController::CROSSEDCIRCLE_CHAR = Utils::String::wideStringToString(L"\uf05e");
@ -59,18 +57,12 @@ const std::string ViewController::TICKMARK_CHAR = "\uf14a";
ViewController* ViewController::get()
{
assert(sInstance);
return sInstance;
static ViewController instance;
return &instance;
}
void ViewController::init(Window* window)
{
assert(!sInstance);
sInstance = new ViewController(window);
}
ViewController::ViewController(Window* window)
: GuiComponent(window)
ViewController::ViewController() noexcept
: GuiComponent(Window::getInstance())
, mNoGamesMessageBox(nullptr)
, mCurrentView(nullptr)
, mPreviousView(nullptr)
@ -88,13 +80,6 @@ ViewController::ViewController(Window* window)
mState.viewstyle = AUTOMATIC;
}
ViewController::~ViewController()
{
assert(sInstance == this);
sInstance = nullptr;
UIModeController::deinit();
}
void ViewController::invalidSystemsFileDialog()
{
std::string errorMessage = "COULDN'T PARSE THE SYSTEMS CONFIGURATION FILE.\n"

View file

@ -29,11 +29,8 @@ class SystemView;
class ViewController : public GuiComponent
{
public:
static void init(Window* window);
static ViewController* get();
virtual ~ViewController();
// These functions are called from main().
void invalidSystemsFileDialog();
void noGamesDialog();
@ -131,8 +128,7 @@ public:
static const std::string TICKMARK_CHAR;
private:
ViewController(Window* window);
static ViewController* sInstance;
ViewController() noexcept;
void launch(FileData* game);

View file

@ -55,8 +55,8 @@ void BasicGameListView::populateList(const std::vector<FileData*>& files, FileDa
std::string editingCollection;
std::string inCollectionPrefix;
if (CollectionSystemsManager::get()->isEditing()) {
editingCollection = CollectionSystemsManager::get()->getEditingCollection();
if (CollectionSystemsManager::getInstance()->isEditing()) {
editingCollection = CollectionSystemsManager::getInstance()->getEditingCollection();
isEditing = true;
}
@ -78,7 +78,8 @@ void BasicGameListView::populateList(const std::vector<FileData*>& files, FileDa
// Add a leading tick mark icon to the game name if it's part of the custom collection
// currently being edited.
if (isEditing && (*it)->getType() == GAME) {
if (CollectionSystemsManager::get()->inCustomCollection(editingCollection, (*it))) {
if (CollectionSystemsManager::getInstance()->inCustomCollection(editingCollection,
(*it))) {
if (Settings::getInstance()->getBool("SpecialCharsASCII"))
inCollectionPrefix = "! ";
else
@ -323,7 +324,7 @@ std::vector<HelpPrompt> BasicGameListView::getHelpPrompts()
prompts.push_back(HelpPrompt("thumbstickclick", "random"));
if (mRoot->getSystem()->getThemeFolder() == "custom-collections" &&
!CollectionSystemsManager::get()->isEditing() && mCursorStack.empty() &&
!CollectionSystemsManager::getInstance()->isEditing() && mCursorStack.empty() &&
ViewController::get()->getState().viewing == ViewController::GAME_LIST &&
ViewController::get()->getState().viewstyle != ViewController::BASIC) {
prompts.push_back(HelpPrompt("y", "jump to game"));
@ -334,14 +335,14 @@ std::vector<HelpPrompt> BasicGameListView::getHelpPrompts()
!UIModeController::getInstance()->isUIModeKid() &&
!UIModeController::getInstance()->isUIModeKiosk() &&
(Settings::getInstance()->getBool("FavoritesAddButton") ||
CollectionSystemsManager::get()->isEditing())) {
std::string prompt = CollectionSystemsManager::get()->getEditingCollection();
CollectionSystemsManager::getInstance()->isEditing())) {
std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection();
prompts.push_back(HelpPrompt("y", prompt));
}
else if (mRoot->getSystem()->isGameSystem() &&
mRoot->getSystem()->getThemeFolder() == "custom-collections" &&
CollectionSystemsManager::get()->isEditing()) {
std::string prompt = CollectionSystemsManager::get()->getEditingCollection();
CollectionSystemsManager::getInstance()->isEditing()) {
std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection();
prompts.push_back(HelpPrompt("y", prompt));
}
return prompts;

View file

@ -338,8 +338,8 @@ void DetailedGameListView::updateInfoPanel()
// the first of these so that we can display its game media.
if (file->getSystem()->isCustomCollection() &&
file->getPath() == file->getSystem()->getName()) {
mRandomGame =
CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem());
mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata(
file->getSystem());
if (mRandomGame) {
mThumbnail.setImage(mRandomGame->getThumbnailPath());
mMarquee.setImage(mRandomGame->getMarqueePath(), false, true);

View file

@ -712,14 +712,14 @@ std::vector<HelpPrompt> GridGameListView::getHelpPrompts()
!UIModeController::getInstance()->isUIModeKid() &&
!UIModeController::getInstance()->isUIModeKiosk() &&
(Settings::getInstance()->getBool("FavoritesAddButton") ||
CollectionSystemsManager::get()->isEditing())) {
std::string prompt = CollectionSystemsManager::get()->getEditingCollection();
CollectionSystemsManager::getInstance()->isEditing())) {
std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection();
prompts.push_back(HelpPrompt("y", prompt));
}
else if (mRoot->getSystem()->isGameSystem() &&
mRoot->getSystem()->getThemeFolder() == "custom-collections" &&
CollectionSystemsManager::get()->isEditing()) {
std::string prompt = CollectionSystemsManager::get()->getEditingCollection();
CollectionSystemsManager::getInstance()->isEditing()) {
std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection();
prompts.push_back(HelpPrompt("y", prompt));
}
return prompts;

View file

@ -237,7 +237,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
}
else if (config->isMappedTo("y", input) &&
mRoot->getSystem()->getThemeFolder() == "custom-collections" &&
!CollectionSystemsManager::get()->isEditing() && mCursorStack.empty() &&
!CollectionSystemsManager::getInstance()->isEditing() && mCursorStack.empty() &&
ViewController::get()->getState().viewing == ViewController::GAME_LIST) {
// Jump to the randomly selected game.
if (mRandomGame) {
@ -262,21 +262,21 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
}
else if (config->isMappedTo("y", input) &&
!Settings::getInstance()->getBool("FavoritesAddButton") &&
!CollectionSystemsManager::get()->isEditing()) {
!CollectionSystemsManager::getInstance()->isEditing()) {
return true;
}
else if (config->isMappedTo("y", input) &&
!UIModeController::getInstance()->isUIModeKid() &&
!UIModeController::getInstance()->isUIModeKiosk()) {
// Notify the user if attempting to add a custom collection to a custom collection.
if (CollectionSystemsManager::get()->isEditing() &&
if (CollectionSystemsManager::getInstance()->isEditing() &&
mRoot->getSystem()->isGameSystem() && getCursor()->getType() != PLACEHOLDER &&
getCursor()->getParent()->getPath() == "collections") {
NavigationSounds::getInstance().playThemeNavigationSound(FAVORITESOUND);
mWindow->queueInfoPopup("CAN'T ADD CUSTOM COLLECTIONS TO CUSTOM COLLECTIONS", 4000);
}
// Notify the user if attempting to add a placeholder to a custom collection.
if (CollectionSystemsManager::get()->isEditing() &&
if (CollectionSystemsManager::getInstance()->isEditing() &&
mRoot->getSystem()->isGameSystem() && getCursor()->getType() == PLACEHOLDER) {
NavigationSounds::getInstance().playThemeNavigationSound(FAVORITESOUND);
mWindow->queueInfoPopup("CAN'T ADD PLACEHOLDERS TO CUSTOM COLLECTIONS", 4000);
@ -293,7 +293,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
bool favoritesSorting;
bool removedLastFavorite = false;
bool selectLastEntry = false;
bool isEditing = CollectionSystemsManager::get()->isEditing();
bool isEditing = CollectionSystemsManager::getInstance()->isEditing();
bool foldersOnTop = Settings::getInstance()->getBool("FoldersOnTop");
// If the current list only contains folders, then treat it as if the folders
// are not sorted on top, this way the logic should work exactly as for mixed
@ -439,7 +439,8 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
"AS GAMES TO CUSTOM COLLECTIONS",
4000);
}
else if (CollectionSystemsManager::get()->toggleGameInCollection(entryToUpdate)) {
else if (CollectionSystemsManager::getInstance()->toggleGameInCollection(
entryToUpdate)) {
// As the toggling of the game destroyed this object, we need to get the view
// from ViewController instead of using the reference that existed before the
// destruction. Otherwise we get random crashes.

View file

@ -349,8 +349,8 @@ void VideoGameListView::updateInfoPanel()
// the first of these so that we can display its game media.
if (file->getSystem()->isCustomCollection() &&
file->getPath() == file->getSystem()->getName()) {
mRandomGame =
CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem());
mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata(
file->getSystem());
if (mRandomGame) {
mThumbnail.setImage(mRandomGame->getThumbnailPath());
mMarquee.setImage(mRandomGame->getMarqueePath(), false, true);

View file

@ -14,7 +14,7 @@
#include <SDL2/SDL.h>
AudioManager::AudioManager()
AudioManager::AudioManager() noexcept
{
// Init on construction.
init();

View file

@ -45,7 +45,7 @@ public:
inline static SDL_AudioSpec sAudioFormat;
private:
AudioManager();
AudioManager() noexcept;
static void mixAudio(void* unused, Uint8* stream, int len);
static void mixAudio2(void* unused, Uint8* stream, int len);

View file

@ -30,8 +30,6 @@ extern "C" {
extern int SDL_USER_CECBUTTONDOWN;
extern int SDL_USER_CECBUTTONUP;
CECInput* CECInput::sInstance = nullptr;
#if defined(HAVE_LIBCEC)
static void onAlert(void* /*cbParam*/,
const CEC::libcec_alert type,
@ -80,20 +78,6 @@ static void vchi_tv_and_cec_deinit()
#endif // _RPI_
#endif // HAVE_LIBCEC
void CECInput::init()
{
if (!sInstance)
sInstance = new CECInput();
}
void CECInput::deinit()
{
if (sInstance) {
delete sInstance;
sInstance = nullptr;
}
}
CECInput::CECInput()
: mlibCEC(nullptr)
{

View file

@ -19,18 +19,14 @@ namespace CEC
class CECInput
{
public:
static void init();
static void deinit();
CECInput();
~CECInput();
static std::string getAlertTypeString(const unsigned int _type);
static std::string getOpCodeString(const unsigned int _opCode);
static std::string getKeyCodeString(const unsigned int _keyCode);
private:
CECInput();
~CECInput();
static CECInput* sInstance;
CEC::ICECAdapter* mlibCEC;
};

View file

@ -10,7 +10,6 @@
#include "InputManager.h"
#include "CECInput.h"
#include "Log.h"
#include "Platform.h"
#include "Scripting.h"
@ -32,9 +31,7 @@ int SDL_USER_CECBUTTONUP = -1;
static bool sAltDown = false;
static bool sLguiDown = false;
InputManager* InputManager::sInstance = nullptr;
InputManager::InputManager()
InputManager::InputManager() noexcept
: mKeyboardInputConfig(nullptr)
{
}
@ -45,12 +42,10 @@ InputManager::~InputManager()
deinit();
}
InputManager* InputManager::getInstance()
InputManager& InputManager::getInstance()
{
if (!sInstance)
sInstance = new InputManager();
return sInstance;
static InputManager instance;
return instance;
}
void InputManager::init()
@ -94,7 +89,7 @@ void InputManager::init()
Utils::FileSystem::getHomePath() + "/.emulationstation/" + "es_controller_mappings.cfg";
if (!Utils::FileSystem::exists(mappingsFile))
mappingsFile = ResourceManager::getInstance()->getResourcePath(
mappingsFile = ResourceManager::getInstance().getResourcePath(
":/controllers/es_controller_mappings.cfg");
int controllerMappings = SDL_GameControllerAddMappingsFromFile(mappingsFile.c_str());
@ -116,7 +111,6 @@ void InputManager::init()
SDL_USER_CECBUTTONDOWN = SDL_RegisterEvents(2);
SDL_USER_CECBUTTONUP = SDL_USER_CECBUTTONDOWN + 1;
CECInput::init();
mCECInputConfig = std::make_unique<InputConfig>(DEVICE_CEC, "CEC", CEC_GUID_STRING);
loadInputConfig(mCECInputConfig.get());
}
@ -138,15 +132,8 @@ void InputManager::deinit()
mKeyboardInputConfig.reset();
mCECInputConfig.reset();
CECInput::deinit();
SDL_GameControllerEventState(SDL_DISABLE);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
if (sInstance) {
delete sInstance;
sInstance = nullptr;
}
}
void InputManager::writeDeviceConfig(InputConfig* config)

View file

@ -11,6 +11,8 @@
#ifndef ES_CORE_INPUT_MANAGER_H
#define ES_CORE_INPUT_MANAGER_H
#include "CECInput.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_joystick.h>
@ -25,9 +27,7 @@ union SDL_Event;
class InputManager
{
public:
InputManager();
virtual ~InputManager();
static InputManager* getInstance();
static InputManager& getInstance();
void init();
void deinit();
@ -50,6 +50,9 @@ public:
int getNumJoysticks() { return static_cast<int>(mJoysticks.size()); }
private:
InputManager() noexcept;
virtual ~InputManager();
bool initialized() const { return mKeyboardInputConfig != nullptr; }
bool loadInputConfig(InputConfig* config);
@ -59,7 +62,8 @@ private:
void addControllerByDeviceIndex(Window* window, int deviceIndex);
void removeControllerByJoystickID(Window* window, SDL_JoystickID joyID);
static InputManager* sInstance;
CECInput mCECInput;
static const int DEADZONE_TRIGGERS = 18000;
static const int DEADZONE_THUMBSTICKS = 23000;
bool mConfigFileExists;

View file

@ -26,7 +26,7 @@ MameNames& MameNames::getInstance()
MameNames::MameNames()
{
std::string xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamenames.xml");
std::string xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamenames.xml");
if (!Utils::FileSystem::exists(xmlpath))
return;
@ -54,7 +54,7 @@ MameNames::MameNames()
}
// Read BIOS file.
xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamebioses.xml");
xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamebioses.xml");
if (!Utils::FileSystem::exists(xmlpath))
return;
@ -80,7 +80,7 @@ MameNames::MameNames()
}
// Read device file.
xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamedevices.xml");
xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamedevices.xml");
if (!Utils::FileSystem::exists(xmlpath))
return;

View file

@ -36,7 +36,7 @@ std::shared_ptr<Sound> Sound::getFromTheme(ThemeData* const theme,
if (theme == nullptr) {
LOG(LogDebug) << "Sound::getFromTheme(): Using fallback sound file for \"" << element
<< "\"";
return get(ResourceManager::getInstance()->getResourcePath(":/sounds/" + element + ".wav"));
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav"));
}
LOG(LogDebug) << "Sound::getFromTheme(): Looking for tag <sound name=\"" << element << "\">";
@ -44,7 +44,7 @@ std::shared_ptr<Sound> Sound::getFromTheme(ThemeData* const theme,
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound");
if (!elem || !elem->has("path")) {
LOG(LogDebug) << "Sound::getFromTheme(): Tag not found, using fallback sound file";
return get(ResourceManager::getInstance()->getResourcePath(":/sounds/" + element + ".wav"));
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav"));
}
LOG(LogDebug) << "Sound::getFromTheme(): Tag found, ready to load theme sound file";

View file

@ -77,6 +77,7 @@ public:
bool isPlayingThemeNavigationSound(NavigationSoundsID soundID);
private:
NavigationSounds() noexcept {};
std::vector<std::shared_ptr<Sound>> mNavigationSounds;
};

View file

@ -321,7 +321,7 @@ void ThemeData::parseIncludes(const pugi::xml_node& root)
for (pugi::xml_node node = root.child("include"); node; node = node.next_sibling("include")) {
std::string relPath = resolvePlaceholders(node.text().as_string());
std::string path = Utils::FileSystem::resolveRelativePath(relPath, mPaths.back(), true);
if (!ResourceManager::getInstance()->fileExists(path))
if (!ResourceManager::getInstance().fileExists(path))
throw error << " -> \"" << relPath << "\" not found (resolved to \"" << path << "\")";
error << " -> \"" << relPath << "\"";
@ -512,7 +512,7 @@ void ThemeData::parseElement(const pugi::xml_node& root,
}
case PATH: {
std::string path = Utils::FileSystem::resolveRelativePath(str, mPaths.back(), true);
if (!ResourceManager::getInstance()->fileExists(path)) {
if (!ResourceManager::getInstance().fileExists(path)) {
std::stringstream ss;
// "From theme yadda yadda, included file yadda yadda.
LOG(LogWarning) << error.msg << ":";

View file

@ -24,7 +24,7 @@
#define CLOCK_BACKGROUND_CREATION false
#endif
Window::Window()
Window::Window() noexcept
: mScreensaver(nullptr)
, mMediaViewer(nullptr)
, mLaunchScreen(nullptr)
@ -48,9 +48,6 @@ Window::Window()
, mTopScale(0.5)
, mChangedThemeSet(false)
{
mHelp = new HelpComponent(this);
mBackgroundOverlay = new ImageComponent(this);
mBackgroundOverlayOpacity = 0;
}
Window::~Window()
@ -67,6 +64,12 @@ Window::~Window()
delete mHelp;
}
Window* Window::getInstance()
{
static Window instance;
return &instance;
}
void Window::pushGui(GuiComponent* gui)
{
if (mGuiStack.size() > 0) {
@ -109,9 +112,13 @@ bool Window::init()
return false;
}
InputManager::getInstance()->init();
InputManager::getInstance().init();
ResourceManager::getInstance()->reloadAll();
ResourceManager::getInstance().reloadAll();
mHelp = new HelpComponent(this);
mBackgroundOverlay = new ImageComponent(this);
mBackgroundOverlayOpacity = 0;
// Keep a reference to the default fonts, so they don't keep getting destroyed/recreated.
if (mDefaultFonts.empty()) {
@ -147,8 +154,8 @@ void Window::deinit()
mPostprocessedBackground.reset();
#endif
InputManager::getInstance()->deinit();
ResourceManager::getInstance()->unloadAll();
InputManager::getInstance().deinit();
ResourceManager::getInstance().unloadAll();
Renderer::deinit();
}

View file

@ -75,8 +75,7 @@ public:
virtual void render(const glm::mat4& parentTrans) = 0;
};
Window();
~Window();
static Window* getInstance();
void pushGui(GuiComponent* gui);
void removeGui(GuiComponent* gui);
@ -147,6 +146,9 @@ public:
bool getChangedThemeSet() { return mChangedThemeSet; }
private:
Window() noexcept;
~Window();
void onSleep() { Scripting::fireEvent("sleep"); }
void onWake() { Scripting::fireEvent("wake"); }

View file

@ -26,7 +26,7 @@ void AnimatedImageComponent::load(const AnimationDef* def)
for (size_t i = 0; i < def->frameCount; ++i) {
if (def->frames[i].path != "" &&
!ResourceManager::getInstance()->fileExists(def->frames[i].path)) {
!ResourceManager::getInstance().fileExists(def->frames[i].path)) {
LOG(LogError) << "Missing animation frame " << i << " (\"" << def->frames[i].path
<< "\")";
continue;

View file

@ -269,7 +269,7 @@ std::shared_ptr<TextureResource> HelpComponent::getIconTexture(const char* name)
return nullptr;
}
if (!ResourceManager::getInstance()->fileExists(pathLookup->second)) {
if (!ResourceManager::getInstance().fileExists(pathLookup->second)) {
LOG(LogError) << "Couldn't load help icon \"" << name << "\" as the file \""
<< pathLookup->second << "\" is missing";
return nullptr;

View file

@ -140,8 +140,8 @@ void ImageComponent::setImage(const std::string& path, bool tile, bool linearMag
mDynamic = false;
}
if (path.empty() || !ResourceManager::getInstance()->fileExists(path)) {
if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath))
if (path.empty() || !ResourceManager::getInstance().fileExists(path)) {
if (mDefaultPath.empty() || !ResourceManager::getInstance().fileExists(mDefaultPath))
mTexture.reset();
else
mTexture =

View file

@ -327,7 +327,7 @@ void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
if (elem->has("gameImage")) {
std::string path = elem->get<std::string>("gameImage");
if (!ResourceManager::getInstance()->fileExists(path)) {
if (!ResourceManager::getInstance().fileExists(path)) {
LOG(LogWarning) << "Could not replace default game image, check path: " << path;
}
else {
@ -346,7 +346,7 @@ void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
if (elem->has("folderImage")) {
std::string path = elem->get<std::string>("folderImage");
if (!ResourceManager::getInstance()->fileExists(path)) {
if (!ResourceManager::getInstance().fileExists(path)) {
LOG(LogWarning) << "Could not replace default folder image, check path: " << path;
}
else {
@ -658,7 +658,7 @@ void ImageGridComponent<T>::updateTileAtPos(int tilePos,
std::string imagePath = mEntries.at(imgPos).data.texturePath;
if (ResourceManager::getInstance()->fileExists(imagePath))
if (ResourceManager::getInstance().fileExists(imagePath))
tile->setImage(imagePath);
else if (mEntries.at(imgPos).object->getType() == 2)
tile->setImage(mDefaultFolderTexture);

View file

@ -69,7 +69,7 @@ bool VideoComponent::setVideo(std::string path)
mVideoPath = fullPath;
// If the file exists then set the new video.
if (!fullPath.empty() && ResourceManager::getInstance()->fileExists(fullPath)) {
if (!fullPath.empty() && ResourceManager::getInstance().fileExists(fullPath)) {
// Return true to show that we are going to attempt to play a video.
return true;
}

View file

@ -43,7 +43,7 @@ GuiDetectDevice::GuiDetectDevice(Window* window,
// Device info.
std::stringstream deviceInfo;
int numDevices = InputManager::getInstance()->getNumJoysticks();
int numDevices = InputManager::getInstance().getNumJoysticks();
if (numDevices > 0)
deviceInfo << numDevices << " GAMEPAD" << (numDevices > 1 ? "S" : "") << " DETECTED";
@ -148,7 +148,7 @@ void GuiDetectDevice::update(int deltaTime)
// command line.
if (!mForcedConfig && mFirstRun &&
Utils::FileSystem::exists(InputManager::getConfigPath()) &&
InputManager::getInstance()->getNumConfiguredDevices() > 0) {
InputManager::getInstance().getNumConfiguredDevices() > 0) {
if (mDoneCallback)
mDoneCallback();
delete this; // Delete GUI element.

View file

@ -174,7 +174,7 @@ GuiInputConfig::GuiInputConfig(Window* window,
// GUI buttons.
std::vector<std::shared_ptr<ButtonComponent>> buttons;
std::function<void()> okFunction = [this, okCallback] {
InputManager::getInstance()->writeDeviceConfig(mTargetConfig); // Save.
InputManager::getInstance().writeDeviceConfig(mTargetConfig); // Save.
if (okCallback)
okCallback();
delete this;

View file

@ -44,7 +44,7 @@ namespace Renderer
size_t width = 0;
size_t height = 0;
ResourceData resData =
ResourceManager::getInstance()->getFileData(":/graphics/window_icon_256.png");
ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png");
std::vector<unsigned char> rawData =
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height);

View file

@ -40,7 +40,7 @@ namespace Renderer
std::string shaderCode;
// This will load the entire GLSL source code into the string variable.
const ResourceData& shaderData = ResourceManager::getInstance()->getFileData(path);
const ResourceData& shaderData = ResourceManager::getInstance().getFileData(path);
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
// Define the GLSL version (version 120 = OpenGL 2.1).

View file

@ -128,7 +128,7 @@ std::shared_ptr<Font> Font::get(int size, const std::string& path)
std::shared_ptr<Font> font = std::shared_ptr<Font>(new Font(def.second, def.first));
sFontMap[def] = std::weak_ptr<Font>(font);
ResourceManager::getInstance()->addReloadable(font);
ResourceManager::getInstance().addReloadable(font);
return font;
}
@ -243,25 +243,25 @@ std::vector<std::string> getFallbackFontPaths()
// Standard fonts, let's include them here for exception handling purposes even though that's
// not really the correct location. (The application will crash if they are missing.)
ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Regular.ttf");
ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-SemiBold.ttf");
ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Bold.ttf");
ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-Regular.ttf");
ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-SemiBold.ttf");
ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-Bold.ttf");
// Vera sans Unicode.
fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/DejaVuSans.ttf"));
fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/DejaVuSans.ttf"));
// GNU FreeFont monospaced.
fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/FreeMono.ttf"));
fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/FreeMono.ttf"));
// Various languages, such as Japanese and Chinese.
fontPaths.push_back(
ResourceManager::getInstance()->getResourcePath(":/fonts/DroidSansFallbackFull.ttf"));
ResourceManager::getInstance().getResourcePath(":/fonts/DroidSansFallbackFull.ttf"));
// Korean.
fontPaths.push_back(
ResourceManager::getInstance()->getResourcePath(":/fonts/NanumMyeongjo.ttf"));
ResourceManager::getInstance().getResourcePath(":/fonts/NanumMyeongjo.ttf"));
// Font Awesome icon glyphs, used for various special symbols like stars, folders etc.
fontPaths.push_back(
ResourceManager::getInstance()->getResourcePath(":/fonts/fontawesome-webfont.ttf"));
ResourceManager::getInstance().getResourcePath(":/fonts/fontawesome-webfont.ttf"));
// This is only needed for some really rare special characters.
fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/Ubuntu-C.ttf"));
fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/Ubuntu-C.ttf"));
fontPaths.shrink_to_fit();
return fontPaths;
@ -281,7 +281,7 @@ FT_Face Font::getFaceForChar(unsigned int id)
// i == 0 -> mPath
// Otherwise, take from fallbackFonts.
const std::string& path = (i == 0 ? mPath : fallbackFonts.at(i - 1));
ResourceData data = ResourceManager::getInstance()->getFileData(path);
ResourceData data = ResourceManager::getInstance().getFileData(path);
mFaceCache[i] = std::unique_ptr<FontFace>(new FontFace(std::move(data), mSize));
fit = mFaceCache.find(i);
}

View file

@ -90,8 +90,8 @@ public:
float getHeight(float lineSpacing = 1.5f) const;
float getLetterHeight();
void reload(std::shared_ptr<ResourceManager>& rm) override { rebuildTextures(); }
void unload(std::shared_ptr<ResourceManager>& rm) override { unloadTextures(); }
void reload(ResourceManager& rm) override { rebuildTextures(); }
void unload(ResourceManager& rm) override { unloadTextures(); }
int getSize() const { return mSize; }
const std::string& getPath() const { return mPath; }

View file

@ -19,14 +19,10 @@
auto array_deleter = [](unsigned char* p) { delete[] p; };
std::shared_ptr<ResourceManager> ResourceManager::sInstance = nullptr;
std::shared_ptr<ResourceManager>& ResourceManager::getInstance()
ResourceManager& ResourceManager::getInstance()
{
if (!sInstance)
sInstance = std::shared_ptr<ResourceManager>(new ResourceManager());
return sInstance;
static ResourceManager instance;
return instance;
}
std::string ResourceManager::getResourcePath(const std::string& path, bool terminateOnFailure) const
@ -145,7 +141,7 @@ void ResourceManager::unloadAll()
auto iter = mReloadables.cbegin();
while (iter != mReloadables.cend()) {
if (!iter->expired()) {
iter->lock()->unload(sInstance);
iter->lock()->unload(getInstance());
++iter;
}
else {
@ -159,7 +155,7 @@ void ResourceManager::reloadAll()
auto iter = mReloadables.cbegin();
while (iter != mReloadables.cend()) {
if (!iter->expired()) {
iter->lock()->reload(sInstance);
iter->lock()->reload(getInstance());
++iter;
}
else {

View file

@ -28,14 +28,14 @@ class ResourceManager;
class IReloadable
{
public:
virtual void unload(std::shared_ptr<ResourceManager>& rm) = 0;
virtual void reload(std::shared_ptr<ResourceManager>& rm) = 0;
virtual void unload(ResourceManager& rm) = 0;
virtual void reload(ResourceManager& rm) = 0;
};
class ResourceManager
{
public:
static std::shared_ptr<ResourceManager>& getInstance();
static ResourceManager& getInstance();
void addReloadable(std::weak_ptr<IReloadable> reloadable);
@ -47,9 +47,8 @@ public:
bool fileExists(const std::string& path) const;
private:
ResourceManager() {}
ResourceManager() noexcept {}
static std::shared_ptr<ResourceManager> sInstance;
std::list<std::weak_ptr<IReloadable>> mReloadables;
ResourceData loadFile(const std::string& path) const;

View file

@ -179,8 +179,7 @@ bool TextureData::load()
// Need to load. See if there is a file.
if (!mPath.empty()) {
std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance();
const ResourceData& data = rm->getFileData(mPath);
const ResourceData& data = ResourceManager::getInstance().getFileData(mPath);
// Is it an SVG?
if (Utils::String::toLower(mPath.substr(mPath.size() - 4, std::string::npos)) == ".svg") {
mScalable = true;

View file

@ -148,14 +148,12 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
bool linearMagnify,
bool forceRasterization)
{
std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance();
const std::string canonicalPath = Utils::FileSystem::getCanonicalPath(path);
if (canonicalPath.empty()) {
std::shared_ptr<TextureResource> tex(
new TextureResource("", tile, false, linearMagnify, forceRasterization));
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
rm->addReloadable(tex);
ResourceManager::getInstance().addReloadable(tex);
return tex;
}
@ -182,7 +180,7 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
}
// Add it to the reloadable list.
rm->addReloadable(tex);
ResourceManager::getInstance().addReloadable(tex);
// Force load it if necessary. Note that it may get dumped from VRAM if we run low.
if (forceLoad) {
@ -241,7 +239,7 @@ size_t TextureResource::getTotalTextureSize()
return total;
}
void TextureResource::unload(std::shared_ptr<ResourceManager>& /*rm*/)
void TextureResource::unload(ResourceManager& /*rm*/)
{
// Release the texture's resources.
std::shared_ptr<TextureData> data;
@ -254,7 +252,7 @@ void TextureResource::unload(std::shared_ptr<ResourceManager>& /*rm*/)
data->releaseRAM();
}
void TextureResource::reload(std::shared_ptr<ResourceManager>& /*rm*/)
void TextureResource::reload(ResourceManager& /*rm*/)
{
// For dynamically loaded textures the texture manager will load them on demand.
// For manually loaded textures we have to reload them here.

View file

@ -68,8 +68,8 @@ protected:
bool dynamic,
bool linearMagnify,
bool forceRasterization);
virtual void unload(std::shared_ptr<ResourceManager>& rm);
virtual void reload(std::shared_ptr<ResourceManager>& rm);
virtual void unload(ResourceManager& rm);
virtual void reload(ResourceManager& rm);
private:
// mTextureData is used for textures that are not loaded from a file - these ones