From b6d29714c7dc782fae4124267368b3783e21ee46 Mon Sep 17 00:00:00 2001 From: dimok789 Date: Fri, 4 Nov 2016 20:47:39 +0100 Subject: [PATCH] - filter homebrew launcher itself from the list of homebrews (issue 13) - fixed random freeze caused from multi threaded access to elements list in a frame (issue 6) - changed maximum depth of ELF file searching to 1 sub-directory only - fixed wrong homebrew buttons order display in some cases (issue 15) - bump hbl version to 1.3 --- meta/meta.xml | 4 +- src/common/common.h | 2 +- src/fs/DirList.cpp | 17 +++++-- src/fs/DirList.h | 7 +-- src/gui/GuiFrame.cpp | 99 ++++++++++++++++++++++++++++--------- src/gui/GuiFrame.h | 11 +++++ src/menu/HomebrewWindow.cpp | 10 ++-- src/menu/ProgressWindow.cpp | 22 ++++++++- src/menu/ProgressWindow.h | 5 ++ src/menu/TcpReceiver.cpp | 3 ++ 10 files changed, 140 insertions(+), 40 deletions(-) diff --git a/meta/meta.xml b/meta/meta.xml index 3b083e4..60d3887 100644 --- a/meta/meta.xml +++ b/meta/meta.xml @@ -2,8 +2,8 @@ Homebrew Launcher Dimok - 1.2 - 20160402210000 + 1.3 + 20161104210000 WiiU Homebrew Launcher Loads WiiU homebrew from SD card and from network. diff --git a/src/common/common.h b/src/common/common.h index 47c704b..3f2aafa 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -7,7 +7,7 @@ extern "C" { #include "os_defs.h" -#define HBL_VERSION "v1.2" +#define HBL_VERSION "v1.3" #define CAFE_OS_SD_PATH "/vol/external01" #define SD_PATH "sd:" diff --git a/src/fs/DirList.cpp b/src/fs/DirList.cpp index 147deaf..c37b504 100644 --- a/src/fs/DirList.cpp +++ b/src/fs/DirList.cpp @@ -39,11 +39,12 @@ DirList::DirList() { Flags = 0; Filter = 0; + Depth = 0; } -DirList::DirList(const std::string & path, const char *filter, u32 flags) +DirList::DirList(const std::string & path, const char *filter, u32 flags, u32 maxDepth) { - this->LoadPath(path, filter, flags); + this->LoadPath(path, filter, flags, maxDepth); this->SortList(); } @@ -52,12 +53,13 @@ DirList::~DirList() ClearList(); } -bool DirList::LoadPath(const std::string & folder, const char *filter, u32 flags) +bool DirList::LoadPath(const std::string & folder, const char *filter, u32 flags, u32 maxDepth) { if(folder.empty()) return false; Flags = flags; Filter = filter; + Depth = maxDepth; std::string folderpath(folder); u32 length = folderpath.size(); @@ -69,6 +71,10 @@ bool DirList::LoadPath(const std::string & folder, const char *filter, u32 flags if(length > 0 && folderpath[length-1] == '/') folderpath.erase(length-1); + //! add root slash if missing + if(folderpath.find('/') == std::string::npos) + folderpath += '/'; + return InternalLoadPath(folderpath); } @@ -94,14 +100,17 @@ bool DirList::InternalLoadPath(std::string &folderpath) if(strcmp(filename,".") == 0 || strcmp(filename,"..") == 0) continue; - if(Flags & CheckSubfolders) + if((Flags & CheckSubfolders) && (Depth > 0)) { int length = folderpath.size(); if(length > 2 && folderpath[length-1] != '/') folderpath += '/'; folderpath += filename; + + Depth--; InternalLoadPath(folderpath); folderpath.erase(length); + Depth++; } if(!(Flags & Dirs)) diff --git a/src/fs/DirList.h b/src/fs/DirList.h index 2a34208..ea5c20c 100644 --- a/src/fs/DirList.h +++ b/src/fs/DirList.h @@ -29,7 +29,7 @@ #include #include -#include +#include "common/types.h" typedef struct { @@ -45,11 +45,11 @@ public: //!\param path Path from where to load the filelist of all files //!\param filter A fileext that needs to be filtered //!\param flags search/filter flags from the enum - DirList(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + DirList(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs, u32 maxDepth = 0xffffffff); //!Destructor virtual ~DirList(); //! Load all the files from a directory - bool LoadPath(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + bool LoadPath(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs, u32 maxDepth = 0xffffffff); //! Get a filename of the list //!\param list index const char * GetFilename(int index) const; @@ -88,6 +88,7 @@ protected: inline bool valid(u32 pos) const { return (pos < FileInfo.size()); }; u32 Flags; + u32 Depth; const char *Filter; std::vector FileInfo; }; diff --git a/src/gui/GuiFrame.cpp b/src/gui/GuiFrame.cpp index 22f4767..77552c8 100644 --- a/src/gui/GuiFrame.cpp +++ b/src/gui/GuiFrame.cpp @@ -51,9 +51,16 @@ void GuiFrame::append(GuiElement* e) if (e == NULL) return; - remove(e); - elements.push_back(e); - e->setParent(this); + e->setParent(this); + + ListChangeElement elem; + elem.addElement = true; + elem.position = -1; + elem.element = e; + + queueMutex.lock(); + listChangeQueue.push(elem); + queueMutex.unlock(); } void GuiFrame::insert(GuiElement* e, u32 index) @@ -61,9 +68,16 @@ void GuiFrame::insert(GuiElement* e, u32 index) if (e == NULL || (index >= elements.size())) return; - remove(e); - elements.insert(elements.begin()+index, e); - e->setParent(this); + e->setParent(this); + + ListChangeElement elem; + elem.addElement = true; + elem.position = index; + elem.element = e; + + queueMutex.lock(); + listChangeQueue.push(elem); + queueMutex.unlock(); } void GuiFrame::remove(GuiElement* e) @@ -71,14 +85,14 @@ void GuiFrame::remove(GuiElement* e) if (e == NULL) return; - for (u32 i = 0; i < elements.size(); ++i) - { - if(e == elements[i]) - { - elements.erase(elements.begin()+i); - break; - } - } + ListChangeElement elem; + elem.addElement = false; + elem.position = -1; + elem.element = e; + + queueMutex.lock(); + listChangeQueue.push(elem); + queueMutex.unlock(); } void GuiFrame::removeAll() @@ -185,18 +199,21 @@ void GuiFrame::draw(CVideo * v) void GuiFrame::updateEffects() { - if(!this->isVisible() && parentElement) - return; + if(this->isVisible() || parentElement) + { + GuiElement::updateEffects(); - GuiElement::updateEffects(); + //! render appended items next frame but allow stop of render if size is reached + u32 size = elements.size(); - //! render appended items next frame but allow stop of render if size is reached - u32 size = elements.size(); + for (u32 i = 0; i < size && i < elements.size(); ++i) + { + elements[i]->updateEffects(); + } + } - for (u32 i = 0; i < size && i < elements.size(); ++i) - { - elements[i]->updateEffects(); - } + //! at the end of main loop which this function represents append pending elements + updateElementList(); } void GuiFrame::update(GuiController * c) @@ -212,3 +229,39 @@ void GuiFrame::update(GuiController * c) elements[i]->update(c); } } + +void GuiFrame::updateElementList(void) +{ + if(listChangeQueue.empty() == false) + { + queueMutex.lock(); + while(!listChangeQueue.empty()) + { + ListChangeElement & listChange = listChangeQueue.front(); + + for (u32 i = 0; i < elements.size(); ++i) + { + if(listChange.element == elements[i]) + { + elements.erase(elements.begin()+i); + break; + } + } + + if(listChange.addElement) + { + if(listChange.position >= 0) + { + elements.insert(elements.begin()+listChange.position, listChange.element); + } + else + { + elements.push_back(listChange.element); + } + } + listChangeQueue.pop(); + } + queueMutex.unlock(); + } + +} diff --git a/src/gui/GuiFrame.h b/src/gui/GuiFrame.h index d780684..2a1eeee 100644 --- a/src/gui/GuiFrame.h +++ b/src/gui/GuiFrame.h @@ -91,6 +91,17 @@ class GuiFrame : public GuiElement bool dim; //! Enable/disable dim of a window only GuiFrame *parent; //!< Parent Window std::vector elements; //!< Contains all elements within the GuiFrame + + void updateElementList(void); + + struct ListChangeElement + { + bool addElement; + int position; + GuiElement *element; + }; + std::queue listChangeQueue; + CMutex queueMutex; }; #endif diff --git a/src/menu/HomebrewWindow.cpp b/src/menu/HomebrewWindow.cpp index 64d99dd..0560b0c 100644 --- a/src/menu/HomebrewWindow.cpp +++ b/src/menu/HomebrewWindow.cpp @@ -52,15 +52,15 @@ HomebrewWindow::HomebrewWindow(int w, int h) currentLeftPosition = 0; listOffset = 0; - DirList dirList("sd:/wiiu/apps", ".elf", DirList::Files | DirList::CheckSubfolders); + DirList dirList("sd:/wiiu/apps", ".elf", DirList::Files | DirList::CheckSubfolders, 1); dirList.SortList(); for(int i = 0; i < dirList.GetFilecount(); i++) { //! skip our own application in the listing - //!if(strcasecmp(dirList.GetFilename(i), "homebrew_launcher.elf") == 0) - //! continue; + if(strcasecmp(dirList.GetFilename(i), "homebrew_launcher.elf") == 0) + continue; //! skip hidden linux and mac files if(dirList.GetFilename(i)[0] == '.' || dirList.GetFilename(i)[0] == '_') @@ -124,8 +124,8 @@ HomebrewWindow::HomebrewWindow(int w, int h) homebrewButtons[idx].button->setLabel(homebrewButtons[idx].nameLabel, 0); homebrewButtons[idx].button->setLabel(homebrewButtons[idx].descriptionLabel, 1); homebrewButtons[idx].button->setIcon(homebrewButtons[idx].iconImg); - float fXOffset = (i / MAX_BUTTONS_ON_PAGE) * width; - float fYOffset = (homebrewButtons[idx].image->getHeight() + 20.0f) * 1.5f - (homebrewButtons[idx].image->getHeight() + 20) * (i % MAX_BUTTONS_ON_PAGE); + float fXOffset = (idx / MAX_BUTTONS_ON_PAGE) * width; + float fYOffset = (homebrewButtons[idx].image->getHeight() + 20.0f) * 1.5f - (homebrewButtons[idx].image->getHeight() + 20) * (idx % MAX_BUTTONS_ON_PAGE); homebrewButtons[idx].button->setPosition(currentLeftPosition + fXOffset, fYOffset); homebrewButtons[idx].button->setTrigger(&touchTrigger); homebrewButtons[idx].button->setTrigger(&wpadTouchTrigger); diff --git a/src/menu/ProgressWindow.cpp b/src/menu/ProgressWindow.cpp index c93295f..57bd6c3 100644 --- a/src/menu/ProgressWindow.cpp +++ b/src/menu/ProgressWindow.cpp @@ -24,6 +24,8 @@ ProgressWindow::ProgressWindow(const std::string & title) , progressImageBlack(bgImage.getWidth(), bgImage.getHeight()/2, (GX2Color){0, 0, 0, 255}) , progressImageColored(bgImage.getWidth(), bgImage.getHeight()/2, (GX2Color){0, 0, 0, 255}) { + titleChanged = false; + currentTitle = title; width = bgImage.getWidth(); height = bgImage.getHeight(); @@ -42,7 +44,7 @@ ProgressWindow::ProgressWindow(const std::string & title) titleText.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE); titleText.setPosition(50, 0); titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f)); - titleText.setText(title.c_str()); + titleText.setText(currentTitle.c_str()); append(&titleText); progressImageColored.setParent(&progressImageBlack); @@ -58,10 +60,26 @@ ProgressWindow::~ProgressWindow() void ProgressWindow::setTitle(const std::string & title) { - titleText.setText(title.c_str()); + titleMutex.lock(); + currentTitle = title; + titleChanged = true; + titleMutex.unlock(); } void ProgressWindow::setProgress(f32 percent) { progressImageColored.setSize(percent * 0.01f * progressImageBlack.getWidth(), progressImageColored.getHeight()); } + +void ProgressWindow::draw(CVideo * v) +{ + if(titleChanged) + { + titleMutex.lock(); + titleChanged = false; + titleText.setText(currentTitle.c_str()); + titleMutex.unlock(); + } + + GuiFrame::draw(v); +} diff --git a/src/menu/ProgressWindow.h b/src/menu/ProgressWindow.h index fd17954..b48e8fd 100644 --- a/src/menu/ProgressWindow.h +++ b/src/menu/ProgressWindow.h @@ -28,6 +28,7 @@ public: void setProgress(f32 percent); void setTitle(const std::string & title); private: + void draw(CVideo * v); GuiText titleText; GuiImageData *bgImageData; @@ -37,6 +38,10 @@ private: GuiTrigger touchTrigger; GuiTrigger wpadTouchTrigger; + + bool titleChanged; + std::string currentTitle; + CMutex titleMutex; }; #endif //_PROGRESS_WINDOW_H_ diff --git a/src/menu/TcpReceiver.cpp b/src/menu/TcpReceiver.cpp index 55f89cd..528d2f6 100644 --- a/src/menu/TcpReceiver.cpp +++ b/src/menu/TcpReceiver.cpp @@ -79,6 +79,9 @@ void TcpReceiver::executeThread() int result = loadToMemory(clientSocket, ipAddress); serverReceiveFinished(this, ipAddress, result); socketclose(clientSocket); + + if(result > 0) + break; } else {