mirror of
https://github.com/wiiu-env/homebrew_launcher.git
synced 2025-02-17 13:06:20 +01:00
- 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:
parent
7cfd09726d
commit
b6d29714c7
@ -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.
|
||||
|
||||
|
@ -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:"
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_
|
||||
|
@ -79,6 +79,9 @@ void TcpReceiver::executeThread()
|
||||
int result = loadToMemory(clientSocket, ipAddress);
|
||||
serverReceiveFinished(this, ipAddress, result);
|
||||
socketclose(clientSocket);
|
||||
|
||||
if(result > 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user