mirror of
https://github.com/wiiu-env/homebrew_launcher.git
synced 2024-09-29 20:28:36 +02: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">
|
<app version="1">
|
||||||
<name>Homebrew Launcher</name>
|
<name>Homebrew Launcher</name>
|
||||||
<coder>Dimok</coder>
|
<coder>Dimok</coder>
|
||||||
<version>1.2</version>
|
<version>1.3</version>
|
||||||
<release_date>20160402210000</release_date>
|
<release_date>20161104210000</release_date>
|
||||||
<short_description>WiiU Homebrew Launcher</short_description>
|
<short_description>WiiU Homebrew Launcher</short_description>
|
||||||
<long_description>Loads WiiU homebrew from SD card and from network.
|
<long_description>Loads WiiU homebrew from SD card and from network.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include "os_defs.h"
|
#include "os_defs.h"
|
||||||
|
|
||||||
#define HBL_VERSION "v1.2"
|
#define HBL_VERSION "v1.3"
|
||||||
|
|
||||||
#define CAFE_OS_SD_PATH "/vol/external01"
|
#define CAFE_OS_SD_PATH "/vol/external01"
|
||||||
#define SD_PATH "sd:"
|
#define SD_PATH "sd:"
|
||||||
|
@ -39,11 +39,12 @@ DirList::DirList()
|
|||||||
{
|
{
|
||||||
Flags = 0;
|
Flags = 0;
|
||||||
Filter = 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();
|
this->SortList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +53,13 @@ DirList::~DirList()
|
|||||||
ClearList();
|
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;
|
if(folder.empty()) return false;
|
||||||
|
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
Filter = filter;
|
Filter = filter;
|
||||||
|
Depth = maxDepth;
|
||||||
|
|
||||||
std::string folderpath(folder);
|
std::string folderpath(folder);
|
||||||
u32 length = folderpath.size();
|
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] == '/')
|
if(length > 0 && folderpath[length-1] == '/')
|
||||||
folderpath.erase(length-1);
|
folderpath.erase(length-1);
|
||||||
|
|
||||||
|
//! add root slash if missing
|
||||||
|
if(folderpath.find('/') == std::string::npos)
|
||||||
|
folderpath += '/';
|
||||||
|
|
||||||
return InternalLoadPath(folderpath);
|
return InternalLoadPath(folderpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,14 +100,17 @@ bool DirList::InternalLoadPath(std::string &folderpath)
|
|||||||
if(strcmp(filename,".") == 0 || strcmp(filename,"..") == 0)
|
if(strcmp(filename,".") == 0 || strcmp(filename,"..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(Flags & CheckSubfolders)
|
if((Flags & CheckSubfolders) && (Depth > 0))
|
||||||
{
|
{
|
||||||
int length = folderpath.size();
|
int length = folderpath.size();
|
||||||
if(length > 2 && folderpath[length-1] != '/')
|
if(length > 2 && folderpath[length-1] != '/')
|
||||||
folderpath += '/';
|
folderpath += '/';
|
||||||
folderpath += filename;
|
folderpath += filename;
|
||||||
|
|
||||||
|
Depth--;
|
||||||
InternalLoadPath(folderpath);
|
InternalLoadPath(folderpath);
|
||||||
folderpath.erase(length);
|
folderpath.erase(length);
|
||||||
|
Depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(Flags & Dirs))
|
if(!(Flags & Dirs))
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <gctypes.h>
|
#include "common/types.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -45,11 +45,11 @@ public:
|
|||||||
//!\param path Path from where to load the filelist of all files
|
//!\param path Path from where to load the filelist of all files
|
||||||
//!\param filter A fileext that needs to be filtered
|
//!\param filter A fileext that needs to be filtered
|
||||||
//!\param flags search/filter flags from the enum
|
//!\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
|
//!Destructor
|
||||||
virtual ~DirList();
|
virtual ~DirList();
|
||||||
//! Load all the files from a directory
|
//! 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
|
//! Get a filename of the list
|
||||||
//!\param list index
|
//!\param list index
|
||||||
const char * GetFilename(int index) const;
|
const char * GetFilename(int index) const;
|
||||||
@ -88,6 +88,7 @@ protected:
|
|||||||
inline bool valid(u32 pos) const { return (pos < FileInfo.size()); };
|
inline bool valid(u32 pos) const { return (pos < FileInfo.size()); };
|
||||||
|
|
||||||
u32 Flags;
|
u32 Flags;
|
||||||
|
u32 Depth;
|
||||||
const char *Filter;
|
const char *Filter;
|
||||||
std::vector<DirEntry> FileInfo;
|
std::vector<DirEntry> FileInfo;
|
||||||
};
|
};
|
||||||
|
@ -51,9 +51,16 @@ void GuiFrame::append(GuiElement* e)
|
|||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
remove(e);
|
e->setParent(this);
|
||||||
elements.push_back(e);
|
|
||||||
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)
|
void GuiFrame::insert(GuiElement* e, u32 index)
|
||||||
@ -61,9 +68,16 @@ void GuiFrame::insert(GuiElement* e, u32 index)
|
|||||||
if (e == NULL || (index >= elements.size()))
|
if (e == NULL || (index >= elements.size()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
remove(e);
|
e->setParent(this);
|
||||||
elements.insert(elements.begin()+index, e);
|
|
||||||
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)
|
void GuiFrame::remove(GuiElement* e)
|
||||||
@ -71,14 +85,14 @@ void GuiFrame::remove(GuiElement* e)
|
|||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (u32 i = 0; i < elements.size(); ++i)
|
ListChangeElement elem;
|
||||||
{
|
elem.addElement = false;
|
||||||
if(e == elements[i])
|
elem.position = -1;
|
||||||
{
|
elem.element = e;
|
||||||
elements.erase(elements.begin()+i);
|
|
||||||
break;
|
queueMutex.lock();
|
||||||
}
|
listChangeQueue.push(elem);
|
||||||
}
|
queueMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::removeAll()
|
void GuiFrame::removeAll()
|
||||||
@ -185,18 +199,21 @@ void GuiFrame::draw(CVideo * v)
|
|||||||
|
|
||||||
void GuiFrame::updateEffects()
|
void GuiFrame::updateEffects()
|
||||||
{
|
{
|
||||||
if(!this->isVisible() && parentElement)
|
if(this->isVisible() || parentElement)
|
||||||
return;
|
{
|
||||||
|
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
|
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
||||||
u32 size = elements.size();
|
{
|
||||||
|
elements[i]->updateEffects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
//! at the end of main loop which this function represents append pending elements
|
||||||
{
|
updateElementList();
|
||||||
elements[i]->updateEffects();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::update(GuiController * c)
|
void GuiFrame::update(GuiController * c)
|
||||||
@ -212,3 +229,39 @@ void GuiFrame::update(GuiController * c)
|
|||||||
elements[i]->update(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
|
bool dim; //! Enable/disable dim of a window only
|
||||||
GuiFrame *parent; //!< Parent Window
|
GuiFrame *parent; //!< Parent Window
|
||||||
std::vector<GuiElement*> elements; //!< Contains all elements within the GuiFrame
|
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
|
#endif
|
||||||
|
@ -52,15 +52,15 @@ HomebrewWindow::HomebrewWindow(int w, int h)
|
|||||||
currentLeftPosition = 0;
|
currentLeftPosition = 0;
|
||||||
listOffset = 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();
|
dirList.SortList();
|
||||||
|
|
||||||
for(int i = 0; i < dirList.GetFilecount(); i++)
|
for(int i = 0; i < dirList.GetFilecount(); i++)
|
||||||
{
|
{
|
||||||
//! skip our own application in the listing
|
//! skip our own application in the listing
|
||||||
//!if(strcasecmp(dirList.GetFilename(i), "homebrew_launcher.elf") == 0)
|
if(strcasecmp(dirList.GetFilename(i), "homebrew_launcher.elf") == 0)
|
||||||
//! continue;
|
continue;
|
||||||
|
|
||||||
//! skip hidden linux and mac files
|
//! skip hidden linux and mac files
|
||||||
if(dirList.GetFilename(i)[0] == '.' || dirList.GetFilename(i)[0] == '_')
|
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].nameLabel, 0);
|
||||||
homebrewButtons[idx].button->setLabel(homebrewButtons[idx].descriptionLabel, 1);
|
homebrewButtons[idx].button->setLabel(homebrewButtons[idx].descriptionLabel, 1);
|
||||||
homebrewButtons[idx].button->setIcon(homebrewButtons[idx].iconImg);
|
homebrewButtons[idx].button->setIcon(homebrewButtons[idx].iconImg);
|
||||||
float fXOffset = (i / MAX_BUTTONS_ON_PAGE) * width;
|
float fXOffset = (idx / 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 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->setPosition(currentLeftPosition + fXOffset, fYOffset);
|
||||||
homebrewButtons[idx].button->setTrigger(&touchTrigger);
|
homebrewButtons[idx].button->setTrigger(&touchTrigger);
|
||||||
homebrewButtons[idx].button->setTrigger(&wpadTouchTrigger);
|
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})
|
, progressImageBlack(bgImage.getWidth(), bgImage.getHeight()/2, (GX2Color){0, 0, 0, 255})
|
||||||
, progressImageColored(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();
|
width = bgImage.getWidth();
|
||||||
height = bgImage.getHeight();
|
height = bgImage.getHeight();
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ ProgressWindow::ProgressWindow(const std::string & title)
|
|||||||
titleText.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);
|
titleText.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);
|
||||||
titleText.setPosition(50, 0);
|
titleText.setPosition(50, 0);
|
||||||
titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));
|
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);
|
append(&titleText);
|
||||||
|
|
||||||
progressImageColored.setParent(&progressImageBlack);
|
progressImageColored.setParent(&progressImageBlack);
|
||||||
@ -58,10 +60,26 @@ ProgressWindow::~ProgressWindow()
|
|||||||
|
|
||||||
void ProgressWindow::setTitle(const std::string & title)
|
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)
|
void ProgressWindow::setProgress(f32 percent)
|
||||||
{
|
{
|
||||||
progressImageColored.setSize(percent * 0.01f * progressImageBlack.getWidth(), progressImageColored.getHeight());
|
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 setProgress(f32 percent);
|
||||||
void setTitle(const std::string & title);
|
void setTitle(const std::string & title);
|
||||||
private:
|
private:
|
||||||
|
void draw(CVideo * v);
|
||||||
|
|
||||||
GuiText titleText;
|
GuiText titleText;
|
||||||
GuiImageData *bgImageData;
|
GuiImageData *bgImageData;
|
||||||
@ -37,6 +38,10 @@ private:
|
|||||||
|
|
||||||
GuiTrigger touchTrigger;
|
GuiTrigger touchTrigger;
|
||||||
GuiTrigger wpadTouchTrigger;
|
GuiTrigger wpadTouchTrigger;
|
||||||
|
|
||||||
|
bool titleChanged;
|
||||||
|
std::string currentTitle;
|
||||||
|
CMutex titleMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_PROGRESS_WINDOW_H_
|
#endif //_PROGRESS_WINDOW_H_
|
||||||
|
@ -79,6 +79,9 @@ void TcpReceiver::executeThread()
|
|||||||
int result = loadToMemory(clientSocket, ipAddress);
|
int result = loadToMemory(clientSocket, ipAddress);
|
||||||
serverReceiveFinished(this, ipAddress, result);
|
serverReceiveFinished(this, ipAddress, result);
|
||||||
socketclose(clientSocket);
|
socketclose(clientSocket);
|
||||||
|
|
||||||
|
if(result > 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user