mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Made the automatic gamelist view style work with the new media handling logic.
This commit is contained in:
parent
09bbb925f9
commit
6199f7371d
18
USERGUIDE.md
18
USERGUIDE.md
|
@ -1,8 +1,26 @@
|
||||||
EmulationStation Desktop Edition - User Guide
|
EmulationStation Desktop Edition - User Guide
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
|
**Note:** This document is intended as a quick start guide, for more in-depth information and details on how to compile EmulationStation and perform more advanced configuration, please refer to the [INSTALL.md](INSTALL.md) document.
|
||||||
|
|
||||||
|
|
||||||
### Getting started
|
### Getting started
|
||||||
|
|
||||||
|
Getting started with EmulationStation is very easy, just make sure to install the software properly, either manually as built from source code or using one of the supplied packages. On Windows you'll use the installer instead of a package.
|
||||||
|
|
||||||
|
Upon first startup, ES will create its home directory, by default the location is ~/.emulationstation.
|
||||||
|
|
||||||
|
On Unix this defaults to /home/<username>/.emulationstation/ and on Windows it defaults to C:\Users\<username>\.emulationstation\
|
||||||
|
|
||||||
|
A settings file, `es_settings.cfg` will be generated with all the default settings, and a `es_systems.cfg` file will also be copied from the program resource folder, that contains the game ROM and emulator settings.
|
||||||
|
|
||||||
|
There's a log file in the home directory as well named `es_log.txt`, please refer to this in case on any errors as it should provide information on what went wrong.
|
||||||
|
|
||||||
|
Upon startup with the default settings, ES is set to the gamelist view style `AUTOMATIC`. In this mode the application will look for any game media files (videos and images) and set the view style accordingly. If at least one image is found for any game for a certain system, the view style `DETAILED` will be shown and if at least one video file is found, the view style `VIDEO` will be selected. The gamelist view styles are described in more detail later in this document.
|
||||||
|
|
||||||
|
|
||||||
|
### Main screen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Main menu
|
### Main menu
|
||||||
|
|
|
@ -292,6 +292,8 @@ void GuiMetaDataEd::fetchDone(const ScraperSearchResult& result)
|
||||||
MetaDataList* metadata = nullptr;
|
MetaDataList* metadata = nullptr;
|
||||||
metadata = new MetaDataList(*mMetaData);
|
metadata = new MetaDataList(*mMetaData);
|
||||||
|
|
||||||
|
mMediaFilesUpdated = result.savedNewImages;
|
||||||
|
|
||||||
// Check if any values were manually changed before starting the scraping.
|
// Check if any values were manually changed before starting the scraping.
|
||||||
// If so, it's these values we should compare against when scraping, not
|
// If so, it's these values we should compare against when scraping, not
|
||||||
// the values previously saved for the game.
|
// the values previously saved for the game.
|
||||||
|
@ -356,8 +358,7 @@ void GuiMetaDataEd::close()
|
||||||
std::function<void()> closeFunc;
|
std::function<void()> closeFunc;
|
||||||
closeFunc = [this] { delete this; };
|
closeFunc = [this] { delete this; };
|
||||||
|
|
||||||
if (dirty)
|
if (dirty) {
|
||||||
{
|
|
||||||
// Changes were made, ask if the user wants to save them.
|
// Changes were made, ask if the user wants to save them.
|
||||||
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
||||||
"SAVE CHANGES?",
|
"SAVE CHANGES?",
|
||||||
|
@ -366,6 +367,9 @@ void GuiMetaDataEd::close()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Always save if the media files have been changed (i.e. newly scraped images).
|
||||||
|
if (mMediaFilesUpdated)
|
||||||
|
save();
|
||||||
closeFunc();
|
closeFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ private:
|
||||||
std::function<void()> mDeleteFunc;
|
std::function<void()> mDeleteFunc;
|
||||||
|
|
||||||
bool mMetadataUpdated;
|
bool mMetadataUpdated;
|
||||||
|
bool mMediaFilesUpdated;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_APP_GUIS_GUI_META_DATA_ED_H
|
#endif // ES_APP_GUIS_GUI_META_DATA_ED_H
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
#include "utils/StringUtil.h"
|
#include "utils/StringUtil.h"
|
||||||
#include "FileData.h"
|
#include "FileData.h"
|
||||||
#include "GamesDBJSONScraper.h"
|
#include "GamesDBJSONScraper.h"
|
||||||
#include "ScreenScraper.h"
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "ScreenScraper.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
|
||||||
#include <FreeImage.h>
|
#include <FreeImage.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
@ -45,14 +46,15 @@ std::unique_ptr<ScraperSearchHandle> startMediaURLsFetch(const std::string& game
|
||||||
|
|
||||||
ScraperSearchParams params;
|
ScraperSearchParams params;
|
||||||
// Check if the scraper in the settings still exists as a registered scraping source.
|
// Check if the scraper in the settings still exists as a registered scraping source.
|
||||||
if (scraper_request_funcs.find(name) == scraper_request_funcs.end())
|
if (scraper_request_funcs.find(name) == scraper_request_funcs.end()) {
|
||||||
LOG(LogWarning) << "Warning - Configured scraper (" << name <<
|
LOG(LogWarning) << "Warning - Configured scraper (" << name <<
|
||||||
") unavailable, scraping aborted.";
|
") unavailable, scraping aborted.";
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
// Specifically use the TheGamesDB function as this type of request
|
// Specifically use the TheGamesDB function as this type of request
|
||||||
// will never occur for ScreenScraper.
|
// will never occur for ScreenScraper.
|
||||||
thegamesdb_generate_json_scraper_requests(gameIDs, handle->mRequestQueue,
|
thegamesdb_generate_json_scraper_requests(gameIDs, handle->mRequestQueue, handle->mResults);
|
||||||
handle->mResults);
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +169,8 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result,
|
||||||
|
|
||||||
std::vector<struct mediaFileInfoStruct> scrapeFiles;
|
std::vector<struct mediaFileInfoStruct> scrapeFiles;
|
||||||
|
|
||||||
|
mResult.savedNewImages = false;
|
||||||
|
|
||||||
if (Settings::getInstance()->getBool("Scrape3DBoxes") && result.box3dUrl != "") {
|
if (Settings::getInstance()->getBool("Scrape3DBoxes") && result.box3dUrl != "") {
|
||||||
mediaFileInfo.fileURL = result.box3dUrl;
|
mediaFileInfo.fileURL = result.box3dUrl;
|
||||||
mediaFileInfo.fileFormat = result.box3dFormat;
|
mediaFileInfo.fileFormat = result.box3dFormat;
|
||||||
|
@ -265,11 +269,13 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result,
|
||||||
setError("Error saving resized image. Out of memory? Disk full?");
|
setError("Error saving resized image. Out of memory? Disk full?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mResult.savedNewImages = true;
|
||||||
}
|
}
|
||||||
// If it's not cached, then initiate the download.
|
// If it's not cached, then initiate the download.
|
||||||
else {
|
else {
|
||||||
mFuncs.push_back(ResolvePair(downloadImageAsync(it->fileURL, filePath,
|
mFuncs.push_back(ResolvePair(downloadImageAsync(it->fileURL, filePath,
|
||||||
it->existingMediaFile), [this, filePath] {
|
it->existingMediaFile, mResult.savedNewImages), [this, filePath] {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,12 +306,13 @@ void MDResolveHandle::update()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url,
|
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url,
|
||||||
const std::string& saveAs, const std::string& existingMediaFile)
|
const std::string& saveAs, const std::string& existingMediaFile, bool& savedNewImage)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<ImageDownloadHandle>(new ImageDownloadHandle(
|
return std::unique_ptr<ImageDownloadHandle>(new ImageDownloadHandle(
|
||||||
url,
|
url,
|
||||||
saveAs,
|
saveAs,
|
||||||
existingMediaFile,
|
existingMediaFile,
|
||||||
|
savedNewImage,
|
||||||
Settings::getInstance()->getInt("ScraperResizeMaxWidth"),
|
Settings::getInstance()->getInt("ScraperResizeMaxWidth"),
|
||||||
Settings::getInstance()->getInt("ScraperResizeMaxHeight")));
|
Settings::getInstance()->getInt("ScraperResizeMaxHeight")));
|
||||||
}
|
}
|
||||||
|
@ -314,6 +321,7 @@ ImageDownloadHandle::ImageDownloadHandle(
|
||||||
const std::string& url,
|
const std::string& url,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::string& existingMediaPath,
|
const std::string& existingMediaPath,
|
||||||
|
bool& savedNewImage,
|
||||||
int maxWidth,
|
int maxWidth,
|
||||||
int maxHeight)
|
int maxHeight)
|
||||||
: mSavePath(path),
|
: mSavePath(path),
|
||||||
|
@ -322,6 +330,7 @@ ImageDownloadHandle::ImageDownloadHandle(
|
||||||
mMaxHeight(maxHeight),
|
mMaxHeight(maxHeight),
|
||||||
mReq(new HttpReq(url))
|
mReq(new HttpReq(url))
|
||||||
{
|
{
|
||||||
|
mSavedNewImagePtr = &savedNewImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageDownloadHandle::update()
|
void ImageDownloadHandle::update()
|
||||||
|
@ -377,6 +386,9 @@ void ImageDownloadHandle::update()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this image was successfully saved, update savedNewImages in ScraperSearchResult.
|
||||||
|
*mSavedNewImagePtr = true;
|
||||||
|
|
||||||
setStatus(ASYNC_DONE);
|
setStatus(ASYNC_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,9 @@ struct ScraperSearchResult {
|
||||||
std::string coverFormat;
|
std::string coverFormat;
|
||||||
std::string marqueeFormat;
|
std::string marqueeFormat;
|
||||||
std::string screenshotFormat;
|
std::string screenshotFormat;
|
||||||
|
|
||||||
|
// Indicate whether any new images were downloaded and saved.
|
||||||
|
bool savedNewImages;
|
||||||
};
|
};
|
||||||
|
|
||||||
// So let me explain why I've abstracted this so heavily.
|
// So let me explain why I've abstracted this so heavily.
|
||||||
|
@ -184,6 +187,7 @@ public:
|
||||||
const std::string& url,
|
const std::string& url,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::string& existingMediaPath,
|
const std::string& existingMediaPath,
|
||||||
|
bool& savedNewImage,
|
||||||
int maxWidth,
|
int maxWidth,
|
||||||
int maxHeight);
|
int maxHeight);
|
||||||
|
|
||||||
|
@ -193,6 +197,7 @@ private:
|
||||||
std::unique_ptr<HttpReq> mReq;
|
std::unique_ptr<HttpReq> mReq;
|
||||||
std::string mSavePath;
|
std::string mSavePath;
|
||||||
std::string mExistingMediaFile;
|
std::string mExistingMediaFile;
|
||||||
|
bool *mSavedNewImagePtr;
|
||||||
int mMaxWidth;
|
int mMaxWidth;
|
||||||
int mMaxHeight;
|
int mMaxHeight;
|
||||||
};
|
};
|
||||||
|
@ -206,7 +211,7 @@ std::string getSaveAsPath(const ScraperSearchParams& params,
|
||||||
// Will resize according to Settings::getInt("ScraperResizeMaxWidth") and
|
// Will resize according to Settings::getInt("ScraperResizeMaxWidth") and
|
||||||
// Settings::getInt("ScraperResizeMaxHeight").
|
// Settings::getInt("ScraperResizeMaxHeight").
|
||||||
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url,
|
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url,
|
||||||
const std::string& saveAs, const std::string& existingMediaPath);
|
const std::string& saveAs, const std::string& existingMediaPath, bool& savedNewImage);
|
||||||
|
|
||||||
// Resolves all metadata assets that need to be downloaded.
|
// Resolves all metadata assets that need to be downloaded.
|
||||||
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result,
|
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result,
|
||||||
|
|
|
@ -326,7 +326,7 @@ std::shared_ptr<IGameListView> ViewController::getGameListView(SystemData* syste
|
||||||
selectedViewType = VIDEO;
|
selectedViewType = VIDEO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!(*it)->getThumbnailPath().empty()) {
|
else if (!(*it)->getImagePath().empty()) {
|
||||||
selectedViewType = DETAILED;
|
selectedViewType = DETAILED;
|
||||||
// Don't break out in case any subsequent files have videos.
|
// Don't break out in case any subsequent files have videos.
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,8 @@
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
|
||||||
BasicGameListView::BasicGameListView(
|
BasicGameListView::BasicGameListView(Window* window, FileData* root)
|
||||||
Window* window,
|
: ISimpleGameListView(window, root), mList(window)
|
||||||
FileData* root)
|
|
||||||
: ISimpleGameListView(window, root),
|
|
||||||
mList(window)
|
|
||||||
{
|
{
|
||||||
mList.setSize(mSize.x(), mSize.y() * 0.8f);
|
mList.setSize(mSize.x(), mSize.y() * 0.8f);
|
||||||
mList.setPosition(0, mSize.y() * 0.2f);
|
mList.setPosition(0, mSize.y() * 0.2f);
|
||||||
|
@ -38,8 +35,7 @@ void BasicGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
|
|
||||||
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||||
{
|
{
|
||||||
if (change == FILE_METADATA_CHANGED)
|
if (change == FILE_METADATA_CHANGED) {
|
||||||
{
|
|
||||||
// Might switch to a detailed view.
|
// Might switch to a detailed view.
|
||||||
ViewController::get()->reloadGameListView(this);
|
ViewController::get()->reloadGameListView(this);
|
||||||
return;
|
return;
|
||||||
|
@ -146,6 +142,28 @@ void BasicGameListView::remove(FileData *game, bool deleteFile)
|
||||||
if (deleteFile)
|
if (deleteFile)
|
||||||
Utils::FileSystem::removeFile(game->getPath());
|
Utils::FileSystem::removeFile(game->getPath());
|
||||||
|
|
||||||
|
// Remove all game media files as well.
|
||||||
|
if (Utils::FileSystem::exists(game->getVideoPath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getVideoPath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->getMiximagePath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getMiximagePath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->getScreenshotPath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getScreenshotPath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->getCoverPath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getCoverPath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->getMarqueePath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getMarqueePath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->get3DBoxPath()))
|
||||||
|
Utils::FileSystem::removeFile(game->get3DBoxPath());
|
||||||
|
|
||||||
|
if (Utils::FileSystem::exists(game->getThumbnailPath()))
|
||||||
|
Utils::FileSystem::removeFile(game->getThumbnailPath());
|
||||||
|
|
||||||
FileData* parent = game->getParent();
|
FileData* parent = game->getParent();
|
||||||
// Select next element in list, or previous if none.
|
// Select next element in list, or previous if none.
|
||||||
if (getCursor() == game) {
|
if (getCursor() == game) {
|
||||||
|
@ -164,6 +182,11 @@ void BasicGameListView::remove(FileData *game, bool deleteFile)
|
||||||
if (mList.size() == 0)
|
if (mList.size() == 0)
|
||||||
addPlaceholder();
|
addPlaceholder();
|
||||||
|
|
||||||
|
// If a game has been deleted, immediately remove the entry from gamelist.xml
|
||||||
|
// regardless of the value of the setting SaveGamelistsMode.
|
||||||
|
game->setDeletionFlag();
|
||||||
|
parent->getSystem()->writeMetaData();
|
||||||
|
|
||||||
// Remove before repopulating (removes from parent), then update the view.
|
// Remove before repopulating (removes from parent), then update the view.
|
||||||
delete game;
|
delete game;
|
||||||
onFileChanged(parent, FILE_REMOVED);
|
onFileChanged(parent, FILE_REMOVED);
|
||||||
|
|
|
@ -77,7 +77,7 @@ void Settings::setDefaults()
|
||||||
|
|
||||||
// UI settings.
|
// UI settings.
|
||||||
mStringMap["StartupSystem"] = "";
|
mStringMap["StartupSystem"] = "";
|
||||||
mStringMap["GamelistViewStyle"] = "detailed";
|
mStringMap["GamelistViewStyle"] = "automatic";
|
||||||
mStringMap["TransitionStyle"] = "instant";
|
mStringMap["TransitionStyle"] = "instant";
|
||||||
mStringMap["ThemeSet"] = "";
|
mStringMap["ThemeSet"] = "";
|
||||||
mStringMap["UIMode"] = "Full";
|
mStringMap["UIMode"] = "Full";
|
||||||
|
|
Loading…
Reference in a new issue