- 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
This commit is contained in:
dimok789 2016-11-04 20:47:39 +01:00
parent 7cfd09726d
commit b6d29714c7
10 changed files with 140 additions and 40 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name>Homebrew Launcher</name>
<coder>Dimok</coder>
<version>1.2</version>
<release_date>20160402210000</release_date>
<version>1.3</version>
<release_date>20161104210000</release_date>
<short_description>WiiU Homebrew Launcher</short_description>
<long_description>Loads WiiU homebrew from SD card and from network.

View File

@ -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:"

View File

@ -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))

View File

@ -29,7 +29,7 @@
#include <vector>
#include <string>
#include <gctypes.h>
#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<DirEntry> FileInfo;
};

View File

@ -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();
}
}

View File

@ -91,6 +91,17 @@ class GuiFrame : public GuiElement
bool dim; //! Enable/disable dim of a window only
GuiFrame *parent; //!< Parent Window
std::vector<GuiElement*> elements; //!< Contains all elements within the GuiFrame
void updateElementList(void);
struct ListChangeElement
{
bool addElement;
int position;
GuiElement *element;
};
std::queue<ListChangeElement> listChangeQueue;
CMutex queueMutex;
};
#endif

View File

@ -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);

View File

@ -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);
}

View File

@ -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_

View File

@ -79,6 +79,9 @@ void TcpReceiver::executeThread()
int result = loadToMemory(clientSocket, ipAddress);
serverReceiveFinished(this, ipAddress, result);
socketclose(clientSocket);
if(result > 0)
break;
}
else
{