usbloadergx/source/themes/Theme_Downloader.cpp
dimok321 500dc4020f *Reworked the whole WiiTDB.xml parsing. This is now done with mxml due to a lack of memory the file is now streamed. Now the full wiitdb.xml file with all languages is always used. The update of WiiTDB is also changed. It is now only updated if the version of the wiitdb.xml file does not match the version of the online file.
*WiiTDB now falls back to english if the locale language is not found for Titles/Synopsis
*Some clean up and memory leak fixes in game info prompt and adjusted the info get to the new WiiTDB reading method.
*Added a few new useful functions from WiiXplorer (DownloadToFileWithProgress, ShowError,...)
*Disabled the console output after the GUI is started up. The info is only output to gecko in GUI mode now.
2010-12-03 18:38:57 +00:00

628 lines
20 KiB
C++

/****************************************************************************
* Theme_Downloader
* USB Loader GX 2009
*
* Theme downloader for USB Loader GX
*
* Theme_Downloader.cpp
***************************************************************************/
#include <string.h>
#include <unistd.h>
#include "language/gettext.h"
#include "libwiigui/gui.h"
#include "prompts/PromptWindows.h"
#include "prompts/ProgressWindow.h"
#include "homebrewboot/HomebrewBrowse.h"
#include "network/networkops.h"
#include "themes/Theme_List.h"
#include "themes/CTheme.h"
#include "menu.h"
#include "filelist.h"
#include "FileOperations/fileops.h"
#include "sys.h"
#include "network/http.h"
#include "ZipFile.h"
#include "gecko.h"
/*** Extern variables ***/
extern u8 shutdown;
extern u8 reset;
extern int connection;
int DownloadTheme(const char *url, const char *title)
{
if (!url) return 0;
char filename[255];
memset(filename, 0, sizeof(filename));
int filesize = download_request(url, (char *) &filename);
if (filesize <= 0)
{
WindowPrompt(tr( "Download request failed." ), 0, tr( "OK" ));
return 0;
}
char path[300];
char filepath[300];
snprintf(path, sizeof(path), "%s%s", Settings.theme_downloadpath, title);
CreateSubfolder(path);
snprintf(filepath, sizeof(filepath), "%s/%s", path, filename);
FILE *file = fopen(filepath, "wb");
if (!file)
{
WindowPrompt(tr( "Download failed." ), tr( "Can't create file" ), tr( "OK" ));
return 0;
}
u32 done = 0;
int blocksize = 1024 * 5;
u8 *buffer = new u8[blocksize];
while (done < (u32) filesize)
{
if ((u32) blocksize > filesize - done) blocksize = filesize - done;
ShowProgress(tr( "Downloading file" ), 0, (char*) filename, done, filesize, true);
int ret = network_read(connection, buffer, blocksize);
if (ret < 0)
{
free(buffer);
fclose(file);
remove(path);
ProgressStop();
WindowPrompt(tr( "Download failed." ), tr( "Transfer failed." ), tr( "OK" ));
return 0;
}
else if (ret == 0) break;
fwrite(buffer, 1, blocksize, file);
done += ret;
}
delete[] buffer;
fclose(file);
ProgressStop();
if (done != (u32) filesize)
{
remove(filepath);
WindowPrompt(tr( "Download failed." ), tr( "Connection lost..." ), tr( "OK" ));
return 0;
}
ZipFile zipfile(filepath);
int result = zipfile.ExtractAll(path);
if (result)
{
remove(filepath);
int choice = WindowPrompt(tr( "Successfully extracted theme." ), tr( "Do you want to apply it now?" ),
tr( "Yes" ), tr( "No" ));
if (choice)
{
char real_themepath[1024];
sprintf(real_themepath, "%s", Settings.theme_path);
if (SearchFile(path, "GXtheme.cfg", real_themepath) == true)
{
char *ptr = strrchr(real_themepath, '/');
if (ptr)
{
ptr++;
ptr[0] = '\0';
}
snprintf(Settings.theme_path, sizeof(Settings.theme_path), "%s", real_themepath);
Settings.Save();
Settings.Load();
result = 2;
}
else WindowPrompt(tr( "ERROR: Can't set up theme." ), tr( "GXtheme.cfg not found in any subfolder." ),
tr( "OK" ));
}
}
else WindowPrompt(tr( "Failed to extract." ), tr( "Unsupported format, try to extract manually." ), tr( "OK" ));
return result;
}
static int Theme_Prompt(const char *title, const char *author, GuiImageData *thumbimageData, const char *downloadlink)
{
gprintf("\nTheme_Prompt(%s ,%s, <DATA>, %s)", title, author, downloadlink);
bool leave = false;
int result = 0;
GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
GuiImageData dialogBox(Resources::GetFile("theme_dialogue_box.png"), Resources::GetFileSize("theme_dialogue_box.png"));
GuiImage dialogBoxImg(&dialogBox);
GuiWindow promptWindow(dialogBox.GetWidth(), dialogBox.GetHeight());
promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
promptWindow.SetPosition(0, -10);
GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
GuiTrigger trigB;
trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
GuiText titleTxt(tr( "Theme Title:" ), 18, Theme.prompttext);
titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
titleTxt.SetPosition(230, 30);
GuiText titleTxt2(title, 18, Theme.prompttext);
titleTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
titleTxt2.SetPosition(230, 50);
titleTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, WRAP);
GuiText authorTxt(tr( "Author:" ), 18, Theme.prompttext);
authorTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
authorTxt.SetPosition(230, 100);
GuiText authorTxt2(author, 18, Theme.prompttext);
authorTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
authorTxt2.SetPosition(230, 120);
authorTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, DOTTED);
GuiText downloadBtnTxt(tr( "Download" ), 22, Theme.prompttext);
downloadBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
GuiImage downloadBtnImg(&btnOutline);
if (Settings.wsprompt)
{
downloadBtnTxt.SetWidescreen(Settings.widescreen);
downloadBtnImg.SetWidescreen(Settings.widescreen);
}
GuiButton downloadBtn(&downloadBtnImg, &downloadBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 170, &trigA, btnSoundOver,
btnSoundClick2, 1);
downloadBtn.SetLabel(&downloadBtnTxt);
downloadBtn.SetScale(0.9);
GuiText backBtnTxt(tr( "Back" ), 22, Theme.prompttext);
backBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
GuiImage backBtnImg(&btnOutline);
if (Settings.wsprompt)
{
backBtnTxt.SetWidescreen(Settings.widescreen);
backBtnImg.SetWidescreen(Settings.widescreen);
}
GuiButton backBtn(&backBtnImg, &backBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 220, &trigA, btnSoundOver, btnSoundClick2, 1);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetTrigger(&trigB);
backBtn.SetScale(0.9);
GuiImage ThemeImage(thumbimageData);
ThemeImage.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
ThemeImage.SetPosition(20, 10);
ThemeImage.SetScale(0.8);
ThemeImage.SetScale(0.8);
promptWindow.Append(&dialogBoxImg);
promptWindow.Append(&ThemeImage);
promptWindow.Append(&titleTxt);
promptWindow.Append(&titleTxt2);
promptWindow.Append(&authorTxt);
promptWindow.Append(&authorTxt2);
promptWindow.Append(&downloadBtn);
promptWindow.Append(&backBtn);
HaltGui();
promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50);
mainWindow->SetState(STATE_DISABLED);
mainWindow->Append(&promptWindow);
mainWindow->ChangeFocus(&promptWindow);
ResumeGui();
while (!leave)
{
VIDEO_WaitVSync();
if (shutdown == 1)
Sys_Shutdown();
else if (reset == 1) Sys_Reboot();
if (downloadBtn.GetState() == STATE_CLICKED)
{
int choice = WindowPrompt(tr( "Do you want to download this theme?" ), title, tr( "Yes" ), tr( "Cancel" ));
if (choice)
{
result = DownloadTheme(downloadlink, title);
if (result == 2) leave = true;
}
mainWindow->SetState(STATE_DISABLED);
promptWindow.SetState(STATE_DEFAULT);
mainWindow->ChangeFocus(&promptWindow);
downloadBtn.ResetState();
}
else if (backBtn.GetState() == STATE_CLICKED)
{
leave = true;
backBtn.ResetState();
}
}
promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50);
while (promptWindow.GetEffect() > 0)
usleep(100);
HaltGui();
mainWindow->Remove(&promptWindow);
mainWindow->SetState(STATE_DEFAULT);
ResumeGui();
return result;
}
int Theme_Downloader()
{
int pagesize = 4;
int menu = MENU_NONE;
bool listchanged = false;
char THEME_LINK[70];
sprintf(THEME_LINK, "http://wii.spiffy360.com/themes.php?xml=1&category=1&adult=%d", Settings.godmode);
/*** Image Variables ***/
GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
GuiImageData theme_box_Data(Resources::GetFile("theme_box.png"), Resources::GetFileSize("theme_box.png"));
GuiImageData bgData(Resources::GetFile("settings_background.png"), Resources::GetFileSize("settings_background.png"));
GuiImageData arrow_left(Resources::GetFile("startgame_arrow_left.png"), Resources::GetFileSize("startgame_arrow_left.png"));
GuiImageData arrow_right(Resources::GetFile("startgame_arrow_right.png"), Resources::GetFileSize("startgame_arrow_right.png"));
GuiImageData wifiImgData(Resources::GetFile("Wifi_btn.png"), Resources::GetFileSize("Wifi_btn.png"));
GuiImageData PageindicatorImgData(Resources::GetFile("pageindicator.png"), Resources::GetFileSize("pageindicator.png"));
GuiImage background(&bgData);
/*** Trigger Variables ***/
GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
GuiTrigger trigHome;
trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);
GuiTrigger trigB;
trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
GuiTrigger trigL;
trigL.SetButtonOnlyTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT);
GuiTrigger trigR;
trigR.SetButtonOnlyTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT);
GuiTrigger trigMinus;
trigMinus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0);
GuiTrigger trigPlus;
trigPlus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, 0);
GuiText titleTxt(tr( "Theme Downloader" ), 28, ( GXColor )
{ 0, 0, 0, 255});
titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
titleTxt.SetPosition(0, 40);
GuiImageData *ImageData[pagesize];
GuiImage *Image[pagesize];
GuiImage *theme_box_img[pagesize];
GuiButton *MainButton[pagesize];
GuiText *MainButtonTxt[pagesize];
Theme_List *ThemeList = NULL;
/*** Buttons ***/
for (int i = 0; i < pagesize; i++)
{
ImageData[i] = NULL;
Image[i] = NULL;
MainButtonTxt[i] = NULL;
theme_box_img[i] = new GuiImage(&theme_box_Data);
MainButton[i] = new GuiButton(theme_box_Data.GetWidth(), theme_box_Data.GetHeight());
MainButton[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
MainButton[i]->SetSoundOver(btnSoundOver);
MainButton[i]->SetSoundClick(btnSoundClick);
MainButton[i]->SetImage(theme_box_img[i]);
MainButton[i]->SetEffectGrow();
MainButton[i]->SetTrigger(&trigA);
}
/*** Positions ***/
MainButton[0]->SetPosition(90, 75);
MainButton[1]->SetPosition(340, 75);
MainButton[2]->SetPosition(90, 230);
MainButton[3]->SetPosition(340, 230);
GuiText backBtnTxt(tr( "Back" ), 22, Theme.prompttext);
backBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
GuiImage backBtnImg(&btnOutline);
if (Settings.wsprompt)
{
backBtnTxt.SetWidescreen(Settings.widescreen);
backBtnImg.SetWidescreen(Settings.widescreen);
}
GuiButton backBtn(&backBtnImg, &backBtnImg, 2, 3, -180, 400, &trigA, btnSoundOver, btnSoundClick2, 1);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetTrigger(&trigB);
GuiButton HomeBtn(1, 1);
HomeBtn.SetTrigger(&trigHome);
GuiImage GoLeftImg(&arrow_left);
GuiButton GoLeftBtn(GoLeftImg.GetWidth(), GoLeftImg.GetHeight());
GoLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
GoLeftBtn.SetPosition(25, -25);
GoLeftBtn.SetImage(&GoLeftImg);
GoLeftBtn.SetSoundOver(btnSoundOver);
GoLeftBtn.SetSoundClick(btnSoundClick2);
GoLeftBtn.SetEffectGrow();
GoLeftBtn.SetTrigger(&trigA);
GoLeftBtn.SetTrigger(&trigL);
GoLeftBtn.SetTrigger(&trigMinus);
GuiImage GoRightImg(&arrow_right);
GuiButton GoRightBtn(GoRightImg.GetWidth(), GoRightImg.GetHeight());
GoRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE);
GoRightBtn.SetPosition(-25, -25);
GoRightBtn.SetImage(&GoRightImg);
GoRightBtn.SetSoundOver(btnSoundOver);
GoRightBtn.SetSoundClick(btnSoundClick2);
GoRightBtn.SetEffectGrow();
GoRightBtn.SetTrigger(&trigA);
GoRightBtn.SetTrigger(&trigR);
GoRightBtn.SetTrigger(&trigPlus);
GuiImage PageindicatorImg(&PageindicatorImgData);
GuiText PageindicatorTxt((char *) NULL, 22, ( GXColor )
{ 0, 0, 0, 255});
GuiButton PageIndicatorBtn(PageindicatorImg.GetWidth(), PageindicatorImg.GetHeight());
PageIndicatorBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
PageIndicatorBtn.SetPosition(110, 400);
PageIndicatorBtn.SetImage(&PageindicatorImg);
PageIndicatorBtn.SetLabel(&PageindicatorTxt);
PageIndicatorBtn.SetSoundOver(btnSoundOver);
PageIndicatorBtn.SetSoundClick(btnSoundClick);
PageIndicatorBtn.SetTrigger(&trigA);
PageIndicatorBtn.SetEffectGrow();
GuiImage wifiImg(&wifiImgData);
if (Settings.wsprompt)
{
wifiImg.SetWidescreen(Settings.widescreen);
}
GuiButton wifiBtn(wifiImg.GetWidth(), wifiImg.GetHeight());
wifiBtn.SetImage(&wifiImg);
wifiBtn.SetPosition(500, 400);
wifiBtn.SetSoundOver(btnSoundOver);
wifiBtn.SetSoundClick(btnSoundClick);
wifiBtn.SetEffectGrow();
wifiBtn.SetTrigger(&trigA);
GuiWindow w(screenwidth, screenheight);
HaltGui();
w.Append(&background);
mainWindow->Append(&w);
ResumeGui();
if (!IsNetworkInit()) NetworkInitPrompt();
char url[300];
int currentpage = 1;
int currenttheme = 0;
HaltGui();
w.RemoveAll();
w.Append(&background);
w.Append(&titleTxt);
w.Append(&backBtn);
w.Append(&GoLeftBtn);
w.Append(&GoRightBtn);
w.Append(&PageIndicatorBtn);
w.Append(&wifiBtn);
w.Append(&HomeBtn);
ResumeGui();
ShowProgress(tr( "Downloading Page List:" ), "", (char *) tr( "Please wait..." ), 0, pagesize);
ThemeList = new Theme_List(THEME_LINK);
int ThemesOnPage = ThemeList->GetThemeCount();
if (!ThemesOnPage)
{
WindowPrompt(tr( "No themes found on the site." ), 0, "OK");
menu = MENU_SETTINGS;
}
while (menu == MENU_NONE)
{
HaltGui();
w.RemoveAll();
w.Append(&background);
w.Append(&titleTxt);
w.Append(&backBtn);
w.Append(&GoLeftBtn);
w.Append(&GoRightBtn);
w.Append(&PageIndicatorBtn);
w.Append(&wifiBtn);
w.Append(&HomeBtn);
ResumeGui();
sprintf(url, "%i", currentpage);
PageindicatorTxt.SetText(url);
int n = 0;
for (int i = currenttheme; (i < (currenttheme + pagesize)); i++)
{
ShowProgress(tr( "Downloading image:" ), 0, (char *) ThemeList->GetThemeTitle(i), n, pagesize);
if (MainButtonTxt[n]) delete MainButtonTxt[n];
if (ImageData[n]) delete ImageData[n];
if (Image[n]) delete Image[n];
MainButtonTxt[n] = NULL;
ImageData[n] = NULL;
Image[n] = NULL;
if (i < ThemesOnPage)
{
MainButtonTxt[n] = new GuiText(ThemeList->GetThemeTitle(i), 18, ( GXColor )
{ 0, 0, 0, 255});
MainButtonTxt[n]->SetAlignment(ALIGN_CENTER, ALIGN_TOP);
MainButtonTxt[n]->SetPosition(0, 10);
MainButtonTxt[n]->SetMaxWidth(theme_box_Data.GetWidth() - 10, DOTTED);
sprintf(url, "%s", ThemeList->GetImageLink(i));
char filepath[300];
snprintf(filepath, sizeof(filepath), "%s/tmp/%s.jpg", Settings.theme_downloadpath,
ThemeList->GetThemeTitle(i));
FILE * storefile = fopen(filepath, "rb");
if (!storefile)
{
struct block file = downloadfile(url);
char storepath[300];
snprintf(storepath, sizeof(storepath), "%s/tmp/", Settings.theme_downloadpath);
CreateSubfolder(storepath);
if (file.data)
{
storefile = fopen(filepath, "wb");
fwrite(file.data, 1, file.size, storefile);
fclose(storefile);
}
ImageData[n] = new GuiImageData(file.data, file.size);
free(file.data);
}
else
{
fseek(storefile, 0, SEEK_END);
u32 filesize = ftell(storefile);
u8 *buffer = (u8*) malloc(filesize);
rewind(storefile);
fread(buffer, 1, filesize, storefile);
fclose(storefile);
ImageData[n] = new GuiImageData(buffer, filesize);
free(buffer);
buffer = NULL;
}
Image[n] = new GuiImage(ImageData[n]);
Image[n]->SetScale(0.4);
Image[n]->SetPosition(50, -45);
MainButton[n]->SetIcon(Image[n]);
MainButton[n]->SetLabel(MainButtonTxt[n]);
}
n++;
}
ProgressStop();
HaltGui();
for (int i = 0; i < pagesize; i++)
{
if (MainButtonTxt[i]) w.Append(MainButton[i]);
}
ResumeGui();
listchanged = false;
while (!listchanged)
{
VIDEO_WaitVSync();
if (shutdown == 1)
Sys_Shutdown();
else if (reset == 1)
Sys_Reboot();
else if (wifiBtn.GetState() == STATE_CLICKED)
{
Initialize_Network();
wifiBtn.ResetState();
}
else if (backBtn.GetState() == STATE_CLICKED)
{
listchanged = true;
menu = MENU_SETTINGS;
backBtn.ResetState();
break;
}
else if (GoRightBtn.GetState() == STATE_CLICKED)
{
listchanged = true;
currenttheme += pagesize;
currentpage++;
if (currenttheme >= ThemesOnPage)
{
currentpage = 1;
currenttheme = 0;
}
GoRightBtn.ResetState();
}
else if (GoLeftBtn.GetState() == STATE_CLICKED)
{
listchanged = true;
currenttheme -= pagesize;
currentpage--;
if (currenttheme < 0)
{
currentpage = ceil((ThemesOnPage + 1.0f) / pagesize);
currenttheme = currentpage * pagesize - pagesize;
}
GoLeftBtn.ResetState();
}
for (int i = 0; i < pagesize; i++)
{
if (MainButton[i]->GetState() == STATE_CLICKED)
{
snprintf(url, sizeof(url), "%s", ThemeList->GetDownloadLink(currenttheme + i));
int ret = Theme_Prompt(ThemeList->GetThemeTitle(currenttheme + i), ThemeList->GetThemeAuthor(currenttheme
+ i), ImageData[i], url);
MainButton[i]->ResetState();
if (ret == 2)
{
listchanged = true;
menu = MENU_THEMEDOWNLOADER;
}
}
}
}
}
w.SetEffect(EFFECT_FADE, -20);
while (w.GetEffect() > 0)
usleep(100);
HaltGui();
mainWindow->Remove(&w);
for (int i = 0; i < pagesize; i++)
{
if (MainButton[i]) delete MainButton[i];
if (theme_box_img[i]) delete theme_box_img[i];
if (ImageData[i]) delete ImageData[i];
if (Image[i]) delete Image[i];
if (MainButtonTxt[i]) delete MainButtonTxt[i];
}
if (ThemeList) delete ThemeList;
ThemeList = NULL;
ResumeGui();
return menu;
}