[Scummvm-git-logs] scummvm master -> b248add10614c6e7aaa83d78555b634389c442b0
sev-
noreply at scummvm.org
Sat Jul 2 19:46:18 UTC 2022
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
9936aed687 GUI: Move icon download callbacks to the DialogState
42a2aef1c5 GUI: Add mutex for the GuiManager icon set
8cda1fe870 GUI: Change the mechanism to update the grid launcher after upding the icons
b248add106 GUI: Improve thread-safety for icons set access
Commit: 9936aed68783efc70175fc0a58e8caf58a27d7b0
https://github.com/scummvm/scummvm/commit/9936aed68783efc70175fc0a58e8caf58a27d7b0
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-07-02T21:46:14+02:00
Commit Message:
GUI: Move icon download callbacks to the DialogState
This fixes a crash when hiding the DownloadIconsDialog while
downloading an icons pack.
Changed paths:
gui/downloadiconsdialog.cpp
gui/downloadiconsdialog.h
diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 300e9d27c04..849f56a8dab 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -56,8 +56,102 @@ struct DialogState {
uint32 startTime;
DialogState() { state = kDownloadStateNone; downloadedSize = totalSize = totalFiles = startTime = 0; dialog = nullptr; }
+
+ void downloadList();
+ void proceedDownload();
+
+ void downloadListCallback(Networking::DataResponse response);
+ void downloadFileCallback(Networking::DataResponse response);
+ void errorCallback(Networking::ErrorResponse error);
+
+private:
+ bool takeOneFile();
} static *g_state;
+
+void DialogState::downloadList() {
+ Networking::SessionRequest *rq = session.get("https://downloads.scummvm.org/frs/icons/LIST", "",
+ new Common::Callback<DialogState, Networking::DataResponse>(this, &DialogState::downloadListCallback),
+ new Common::Callback<DialogState, Networking::ErrorResponse>(this, &DialogState::errorCallback),
+ true);
+
+ rq->start();
+}
+
+void DialogState::proceedDownload() {
+ startTime = g_system->getMillis();
+ takeOneFile();
+}
+
+bool DialogState::takeOneFile() {
+ auto f = fileHash.begin();
+ if (f == fileHash.end())
+ return false;
+
+ Common::String fname = f->_key;
+ fileHash.erase(fname);
+
+ Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", fname.c_str());
+ Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + fname, '/');
+
+ Networking::SessionRequest *rq = session.get(url, localFile,
+ new Common::Callback<DialogState, Networking::DataResponse>(this, &DialogState::downloadFileCallback),
+ new Common::Callback<DialogState, Networking::ErrorResponse>(this, &DialogState::errorCallback));
+
+ rq->start();
+ return true;
+}
+
+void DialogState::downloadListCallback(Networking::DataResponse r) {
+ Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
+ Common::MemoryReadStream stream(response->buffer, response->len);
+
+ int nline = 0;
+ while (!stream.eos()) {
+ Common::String s = stream.readString('\n');
+ nline++;
+ if (s.empty())
+ continue;
+
+ size_t pos = s.findFirstOf(',');
+ if (pos == Common::String::npos) {
+ warning("DownloadIconsDialog: wrong string format at line %d: <%s>", nline, s.c_str());
+ continue;
+ }
+
+ fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
+ }
+
+ state = kDownloadStateListDownloaded;
+ if (dialog)
+ dialog->sendCommand(kListDownloadFinishedCmd, 0);
+}
+
+void DialogState::downloadFileCallback(Networking::DataResponse r) {
+ Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
+
+ downloadedSize += response->len;
+ if (response->eos) {
+ if (!takeOneFile()) {
+ state = kDownloadComplete;
+ g_gui.initIconsSet();
+ if (dialog)
+ dialog->sendCommand(kDownloadEndedCmd, 0);
+ return;
+ }
+ }
+
+ if (dialog)
+ dialog->sendCommand(kDownloadProgressCmd, 0);
+}
+
+void DialogState::errorCallback(Networking::ErrorResponse error) {
+ Common::U32String message = Common::U32String::format(_("ERROR %d: %s"), error.httpResponseCode, error.response.c_str());
+
+ if (dialog)
+ dialog->setError(message);
+}
+
static uint32 getDownloadingProgress() {
if (!g_state || g_state->totalSize == 0)
return 0;
@@ -101,7 +195,7 @@ DownloadIconsDialog::DownloadIconsDialog() :
setState(kDownloadStateList);
refreshWidgets();
- downloadList();
+ g_state->downloadList();
} else {
g_state->dialog = this;
@@ -210,7 +304,6 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
break;
case kDownloadEndedCmd:
setState(kDownloadComplete);
- g_gui.initIconsSet();
setResult(1); // Need tell the options to refresh launcher
break;
case kListDownloadFinishedCmd:
@@ -219,7 +312,7 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
break;
case kDownloadProceedCmd:
setState(kDownloadStateDownloading);
- proceedDownload();
+ g_state->proceedDownload();
break;
default:
Dialog::handleCommand(sender, cmd, data);
@@ -269,34 +362,6 @@ void DownloadIconsDialog::refreshWidgets() {
_progressBar->setValue(progress);
}
-void DownloadIconsDialog::downloadListCallback(Networking::DataResponse r) {
- Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
-
- Common::MemoryReadStream stream(response->buffer, response->len);
-
- int nline = 0;
-
- while (!stream.eos()) {
- Common::String s = stream.readString('\n');
-
- nline++;
-
- if (s.empty())
- continue;
-
- size_t pos = s.findFirstOf(',');
-
- if (pos == Common::String::npos) {
- warning("DownloadIconsDialog: wrong string format at line %d: <%s>", nline, s.c_str());
- continue;
- }
-
- g_state->fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
- }
-
- sendCommand(kListDownloadFinishedCmd, 0);
-}
-
void DownloadIconsDialog::setError(Common::U32String &msg) {
_errorText->setLabel(msg);
@@ -304,22 +369,6 @@ void DownloadIconsDialog::setError(Common::U32String &msg) {
_cancelButton->setCmd(kCleanupCmd);
}
-void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
- Common::U32String message = Common::U32String::format(_("ERROR %d: %s"), error.httpResponseCode, error.response.c_str());
-
- if (g_state->dialog)
- g_state->dialog->setError(message);
-}
-
-void DownloadIconsDialog::downloadList() {
- Networking::SessionRequest *rq = g_state->session.get("https://downloads.scummvm.org/frs/icons/LIST", "",
- new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadListCallback),
- new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
- true);
-
- rq->start();
-}
-
void DownloadIconsDialog::calculateList() {
if (!ConfMan.hasKey("iconspath")) {
Common::U32String str(_("ERROR: No icons path set"));
@@ -360,48 +409,5 @@ void DownloadIconsDialog::calculateList() {
setState(kDownloadStateListCalculated);
}
-bool DownloadIconsDialog::takeOneFile() {
- auto f = g_state->fileHash.begin();
-
- if (f == g_state->fileHash.end())
- return false;
-
- Common::String fname = f->_key;
-
- g_state->fileHash.erase(fname);
-
- Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", fname.c_str());
- Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + fname, '/');
-
- Networking::SessionRequest *rq = g_state->session.get(url, localFile,
- new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
- new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback));
-
- rq->start();
-
- return true;
-}
-
-void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
- Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
-
- g_state->downloadedSize += response->len;
-
- if (response->eos) {
- if (!takeOneFile()) {
- sendCommand(kDownloadEndedCmd, 0);
- return;
- }
- }
-
- sendCommand(kDownloadProgressCmd, 0);
-}
-
-void DownloadIconsDialog::proceedDownload() {
- g_state->startTime = g_system->getMillis();
-
- takeOneFile();
-}
-
} // End of namespace GUI
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 1e717aeca07..d03193fcd91 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -73,18 +73,11 @@ public:
void handleTickle() override;
void reflowLayout() override;
- void downloadListCallback(Networking::DataResponse response);
- void downloadFileCallback(Networking::DataResponse response);
- void errorCallback(Networking::ErrorResponse error);
-
void setError(Common::U32String &msg);
private:
- void downloadList();
void calculateList();
- void proceedDownload();
void setState(IconProcessState state);
- bool takeOneFile();
};
} // End of namespace GUI
Commit: 42a2aef1c5ca90bac123572c3d6e379e677d5f41
https://github.com/scummvm/scummvm/commit/42a2aef1c5ca90bac123572c3d6e379e677d5f41
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-07-02T21:46:14+02:00
Commit Message:
GUI: Add mutex for the GuiManager icon set
GuiManager::initIconsSet is called from a callback of the iconset
download dialog, which runs in a separate thread. That means the
iconset can be accessed from two separate thread (the GUI thread,
and the download thread).
This was not an issue until the previous commit as closing the
download dialog while a download was ongoing would crash ScummVM.
But now that the crash is fixed, a race condition was possible.
Changed paths:
gui/gui-manager.cpp
gui/gui-manager.h
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 534b7b4e625..33fffaab5b3 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -114,6 +114,7 @@ struct ArchiveMemberListBackComparator {
}
};
void GuiManager::initIconsSet() {
+ Common::StackLock lock(_iconsMutex);
Common::Archive *dat;
_iconsSet.clear();
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 38d7865bc35..ce23ef8a02c 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -27,6 +27,7 @@
#include "common/stack.h"
#include "common/str.h"
#include "common/list.h"
+#include "common/mutex.h"
#include "gui/ThemeEngine.h"
#include "gui/widget.h"
@@ -91,7 +92,10 @@ public:
ThemeEval *xmlEval() { return _theme->getEvaluator(); }
- Common::SearchSet &getIconsSet() { return _iconsSet; }
+ Common::SearchSet &getIconsSet() {
+ Common::StackLock lock(_iconsMutex);
+ return _iconsSet;
+ }
int16 getGUIWidth() const { return _baseWidth; }
int16 getGUIHeight() const { return _baseHeight; }
@@ -162,6 +166,7 @@ protected:
int _topDialogLeftPadding;
int _topDialogRightPadding;
+ Common::Mutex _iconsMutex;
Common::SearchSet _iconsSet;
// position and time of last mouse click (used to detect double clicks)
Commit: 8cda1fe870e76efd7b13514ab304af64a8187377
https://github.com/scummvm/scummvm/commit/8cda1fe870e76efd7b13514ab304af64a8187377
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-07-02T21:46:14+02:00
Commit Message:
GUI: Change the mechanism to update the grid launcher after upding the icons
The icons download dialog was triggering the grid launcher update after
icons had been downloaded. But that means no update was done if the
dialog had been closed during the download.
Now the GUIManager triggers the update. This fixes the missing update
when hiding the download dialog while downloading an icon set.
Changed paths:
gui/downloadiconsdialog.cpp
gui/gui-manager.cpp
gui/gui-manager.h
gui/launcher.cpp
gui/options.cpp
diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 849f56a8dab..5c07714ed00 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -304,7 +304,6 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
break;
case kDownloadEndedCmd:
setState(kDownloadComplete);
- setResult(1); // Need tell the options to refresh launcher
break;
case kListDownloadFinishedCmd:
setState(kDownloadStateListDownloaded);
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 33fffaab5b3..0ed7abdfdb4 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -59,7 +59,7 @@ enum {
};
// Constructor
-GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false),
+GuiManager::GuiManager() : CommandSender(nullptr), _redrawStatus(kRedrawDisabled), _stateIsSaved(false),
_cursorAnimateCounter(0), _cursorAnimateTimer(0) {
_theme = nullptr;
_useStdCursor = false;
@@ -73,6 +73,8 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false),
_useRTL = false;
+ _iconsSetChanged = false;
+
_topDialogLeftPadding = 0;
_topDialogRightPadding = 0;
@@ -170,6 +172,7 @@ void GuiManager::initIconsSet() {
}
_iconsSet.add(fname, dat);
+ _iconsSetChanged = true;
debug(2, "GUI: Loaded icon file: %s", fname);
}
@@ -506,6 +509,18 @@ void GuiManager::runLoop() {
processEvent(event, activeDialog);
}
+ // If iconsSet was modified, notify dialogs so that they can be updated if needed
+ _iconsMutex.lock();
+ bool iconsChanged = _iconsSetChanged;
+ _iconsSetChanged = false;
+ _iconsMutex.unlock();
+ if (iconsChanged) {
+ for (DialogStack::size_type i = 0; i < _dialogStack.size(); ++i) {
+ setTarget(_dialogStack[i]);
+ sendCommand(kIconsSetLoadedCmd, 0);
+ }
+ }
+
// Delete GuiObject that have been added to the trash for a delayed deletion
Common::List<GuiObjectTrashItem>::iterator it = _guiObjectTrash.begin();
while (it != _guiObjectTrash.end()) {
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index ce23ef8a02c..6f3e2081021 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -45,6 +45,10 @@ namespace Common {
namespace GUI {
+enum {
+ kIconsSetLoadedCmd = 'icns'
+};
+
class Dialog;
class ThemeEval;
class GuiObject;
@@ -65,7 +69,7 @@ typedef Common::FixedStack<Dialog *> DialogStack;
/**
* GUI manager singleton.
*/
-class GuiManager : public Common::Singleton<GuiManager> {
+class GuiManager : public Common::Singleton<GuiManager>, public CommandSender {
friend class Dialog;
friend class Common::Singleton<SingletonBaseType>;
GuiManager();
@@ -168,6 +172,7 @@ protected:
Common::Mutex _iconsMutex;
Common::SearchSet _iconsSet;
+ bool _iconsSetChanged;
// position and time of last mouse click (used to detect double clicks)
struct MousePos {
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 5b3b0231772..b63991d2757 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1477,6 +1477,9 @@ void LauncherGrid::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
ConfMan.flushToDisk();
reflowLayout();
break;
+ case kIconsSetLoadedCmd:
+ rebuild();
+ break;
default:
LauncherDialog::handleCommand(sender, cmd, data);
}
diff --git a/gui/options.cpp b/gui/options.cpp
index 19e3dcc1e2c..ea04dc29985 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2991,12 +2991,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
#ifdef USE_LIBCURL
case kUpdateIconsCmd: {
DownloadIconsDialog dia;
-
- if (dia.runModal() > 0) {
- if (_launcher && _launcher->getType() == kLauncherDisplayGrid)
- _launcher->rebuild();
- }
-
+ dia.runModal();
break;
}
#endif
Commit: b248add10614c6e7aaa83d78555b634389c442b0
https://github.com/scummvm/scummvm/commit/b248add10614c6e7aaa83d78555b634389c442b0
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-07-02T21:46:14+02:00
Commit Message:
GUI: Improve thread-safety for icons set access
The previous commit was not sufficient as getIconsSet() returns a
reference to the SearchSet and it could then be used after the
mutex had been unlocked and while it was being modified in
initIconsSet() called in another thread.
Changed paths:
gui/gui-manager.h
gui/launcher.cpp
gui/widgets/grid.cpp
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 6f3e2081021..3127788b3e0 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -96,10 +96,9 @@ public:
ThemeEval *xmlEval() { return _theme->getEvaluator(); }
- Common::SearchSet &getIconsSet() {
- Common::StackLock lock(_iconsMutex);
- return _iconsSet;
- }
+ void lockIconsSet() { _iconsMutex.lock(); }
+ void unlockIconsSet() { _iconsMutex.unlock(); }
+ Common::SearchSet &getIconsSet() { return _iconsSet; }
int16 getGUIWidth() const { return _baseWidth; }
int16 getGUIHeight() const { return _baseHeight; }
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index b63991d2757..c163a8a47df 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -183,6 +183,7 @@ LauncherDialog::LauncherDialog(const Common::String &dialogName, LauncherChooser
Common::ArchiveMemberList mdFiles;
+ g_gui.lockIconsSet();
g_gui.getIconsSet().listMatchingMembers(mdFiles, "*.xml");
for (Common::ArchiveMemberList::iterator md = mdFiles.begin(); md != mdFiles.end(); ++md) {
if (_metadataParser.loadStream((*md)->createReadStream()) == false) {
@@ -194,6 +195,7 @@ LauncherDialog::LauncherDialog(const Common::String &dialogName, LauncherChooser
}
_metadataParser.close();
}
+ g_gui.unlockIconsSet();
}
LauncherDialog::~LauncherDialog() {
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index 8355133e9ae..ccae86ba5f2 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -291,9 +291,11 @@ Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int re
#ifdef USE_PNG
const Graphics::Surface *srcSurface = nullptr;
Image::PNGDecoder decoder;
+ g_gui.lockIconsSet();
if (g_gui.getIconsSet().hasFile(name)) {
Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(name);
if (!decoder.loadStream(*stream)) {
+ g_gui.unlockIconsSet();
warning("Error decoding PNG");
return surf;
}
@@ -308,10 +310,12 @@ Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int re
} else {
debug(5, "GridWidget: Cannot read file '%s'", name.c_str());
}
+ g_gui.unlockIconsSet();
#else
error("No PNG support compiled");
#endif
} else if (name.hasSuffix(".svg")) {
+ g_gui.lockIconsSet();
if (g_gui.getIconsSet().hasFile(name)) {
Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(name);
Graphics::SVGBitmap *image = nullptr;
@@ -325,6 +329,7 @@ Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int re
} else {
debug(5, "GridWidget: Cannot read file '%s'", name.c_str());
}
+ g_gui.unlockIconsSet();
}
return surf;
}
More information about the Scummvm-git-logs
mailing list