usbloadergx/source/prompts/ProgressWindow.cpp

450 lines
15 KiB
C++
Raw Normal View History

/****************************************************************************
* ProgressWindow
* USB Loader GX 2009
*
* ProgressWindow.cpp
***************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "menu.h"
#include "language/gettext.h"
#include "libwiigui/gui.h"
#include "prompts/ProgressWindow.h"
#include "usbloader/wbfs.h"
#include "usbloader/utils.h"
#include "themes/CTheme.h"
/*** Variables used only in this file ***/
static lwp_t progressthread = LWP_THREAD_NULL;
static ProgressAbortCallback AbortCallback = NULL;
static char progressTitle[100];
static const char * progressMsg1 = NULL;
static const char * progressMsg2 = NULL;
static char progressTime[80];
static char progressSizeLeft[80];
static char progressSpeed[15];
static int showProgress = 0;
static f32 progressDone = 0.0;
static bool showTime = false;
static bool showSize = false;
2009-10-20 01:09:27 +02:00
static bool changed = true;
static s64 gameinstalldone = 0;
static s64 gameinstalltotal = -1;
static time_t start;
/*** Extern variables ***/
extern GuiWindow * mainWindow;
extern float gamesize;
/*** Extern functions ***/
extern void ResumeGui();
extern void HaltGui();
/****************************************************************************
* ProgressCallback mainly for gameinstallation. Can be used for other C app.
2010-09-24 02:48:03 +02:00
***************************************************************************/
extern "C" void ProgressCallback(s64 done, s64 total)
{
gameinstalldone = done;
gameinstalltotal = total;
}
/****************************************************************************
* GameInstallProgress
* GameInstallValue updating function
2010-09-24 02:48:03 +02:00
***************************************************************************/
static void GameInstallProgress()
{
2010-09-24 02:48:03 +02:00
if (gameinstalltotal <= 0) return;
2009-10-20 01:09:27 +02:00
2010-09-24 02:48:03 +02:00
if (gameinstalldone > gameinstalltotal) gameinstalldone = gameinstalltotal;
static u32 expected = 300;
u32 elapsed, h, m, s;
f32 speed = 0;
//Elapsed time
2010-09-24 02:48:03 +02:00
elapsed = time(0) - start;
//Calculate speed in MB/s
2010-09-24 02:48:03 +02:00
if (elapsed > 0) speed = KB_SIZE * gamesize * gameinstalldone / (gameinstalltotal * elapsed);
2010-09-24 02:48:03 +02:00
if (gameinstalldone != gameinstalltotal)
{
//Expected time
2010-09-24 02:48:03 +02:00
if (elapsed) expected = (expected * 3 + elapsed * gameinstalltotal / gameinstalldone) / 4;
//Remaining time
2010-09-24 02:48:03 +02:00
elapsed = (expected > elapsed) ? (expected - elapsed) : 0;
}
//Calculate time values
2010-09-24 02:48:03 +02:00
h = elapsed / 3600;
m = (elapsed / 60) % 60;
s = elapsed % 60;
progressDone = 100.0 * gameinstalldone / gameinstalltotal;
2010-09-24 02:48:03 +02:00
snprintf(progressTime, sizeof(progressTime), "%s %d:%02d:%02d", tr( "Time left:" ), h, m, s);
snprintf(progressSizeLeft, sizeof(progressSizeLeft), "%.2fGB/%.2fGB",
gamesize * gameinstalldone / gameinstalltotal, gamesize);
snprintf(progressSpeed, sizeof(progressSpeed), "%.1fMB/s", speed);
2009-10-20 01:09:27 +02:00
changed = true;
}
/****************************************************************************
* SetupGameInstallProgress
2010-09-24 02:48:03 +02:00
***************************************************************************/
void SetupGameInstallProgress(char * title, char * game)
{
2010-09-24 02:48:03 +02:00
strlcpy(progressTitle, title, sizeof(progressTitle));
progressMsg1 = game;
gameinstalltotal = 1;
showProgress = 1;
showSize = true;
showTime = true;
2010-09-24 02:48:03 +02:00
LWP_ResumeThread(progressthread);
start = time(0);
}
/****************************************************************************
* ProgressWindow
*
* Opens a window, which displays progress to the user. Can either display a
* progress bar showing % completion, or a throbber that only shows that an
* action is in progress.
***************************************************************************/
2010-09-24 02:48:03 +02:00
static void ProgressWindow(const char *title, const char *msg1, const char *msg2)
{
2010-09-24 02:48:03 +02:00
GuiWindow promptWindow(472, 320);
promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
promptWindow.SetPosition(0, -10);
GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
GuiImageData dialogBox(Resources::GetFile("dialogue_box.png"), Resources::GetFileSize("dialogue_box.png"));
GuiTrigger trigA;
2010-09-24 02:48:03 +02:00
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
2010-09-24 02:48:03 +02:00
GuiImage dialogBoxImg(&dialogBox);
2010-10-27 16:45:27 +02:00
if (Settings.wsprompt)
{
2010-09-24 02:48:03 +02:00
dialogBoxImg.SetWidescreen(Settings.widescreen);
}
GuiImageData progressbarOutline(Resources::GetFile("progressbar_outline.png"), Resources::GetFileSize("progressbar_outline.png"));
2010-09-24 02:48:03 +02:00
GuiImage progressbarOutlineImg(&progressbarOutline);
2010-10-27 16:45:27 +02:00
if (Settings.wsprompt)
{
2010-09-24 02:48:03 +02:00
progressbarOutlineImg.SetWidescreen(Settings.widescreen);
}
2010-09-24 02:48:03 +02:00
progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
progressbarOutlineImg.SetPosition(25, 40);
GuiImageData progressbarEmpty(Resources::GetFile("progressbar_empty.png"), Resources::GetFileSize("button_dialogue_box.png"));
2010-09-24 02:48:03 +02:00
GuiImage progressbarEmptyImg(&progressbarEmpty);
progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
progressbarEmptyImg.SetPosition(25, 40);
progressbarEmptyImg.SetTile(100);
GuiImageData progressbar(Resources::GetFile("progressbar.png"), Resources::GetFileSize("progressbar.png"));
2010-09-24 02:48:03 +02:00
GuiImage progressbarImg(&progressbar);
progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
progressbarImg.SetPosition(25, 40);
GuiText titleTxt(title, 26, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
titleTxt.SetPosition(0, 60);
GuiText msg1Txt(msg1, 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
msg1Txt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
if (msg2)
msg1Txt.SetPosition(0, 100);
else
2010-09-24 02:48:03 +02:00
msg1Txt.SetPosition(0, 120);
msg1Txt.SetMaxWidth(430, DOTTED);
GuiText msg2Txt(msg2, 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
msg2Txt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
msg2Txt.SetPosition(0, 125);
msg2Txt.SetMaxWidth(430, DOTTED);
GuiText prsTxt("%", 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
prsTxt.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE);
prsTxt.SetPosition(-188, 40);
GuiText timeTxt((char*) NULL, 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
timeTxt.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
timeTxt.SetPosition(280, -50);
GuiText sizeTxt((char*) NULL, 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
sizeTxt.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
sizeTxt.SetPosition(50, -50);
GuiText speedTxt((char*) NULL, 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
speedTxt.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
speedTxt.SetPosition(50, -74);
GuiText prTxt((char*) NULL, 26, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
2010-09-24 02:48:03 +02:00
prTxt.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
prTxt.SetPosition(200, 40);
2010-10-27 16:45:27 +02:00
if ((Settings.wsprompt) && (Settings.widescreen)) /////////////adjust for widescreen
{
2010-09-24 02:48:03 +02:00
progressbarOutlineImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
progressbarOutlineImg.SetPosition(0, 40);
progressbarEmptyImg.SetPosition(80, 40);
progressbarEmptyImg.SetTile(78);
progressbarImg.SetPosition(80, 40);
msg1Txt.SetMaxWidth(380, DOTTED);
msg2Txt.SetMaxWidth(380, DOTTED);
timeTxt.SetPosition(250, -50);
timeTxt.SetFontSize(20);
speedTxt.SetPosition(90, -74);
speedTxt.SetFontSize(20);
sizeTxt.SetPosition(90, -50);
sizeTxt.SetFontSize(20);
}
GuiText cancelTxt(tr( "Cancel" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color"));
GuiImage cancelImg(&btnOutline);
if (Settings.wsprompt)
{
cancelTxt.SetWidescreen(Settings.widescreen);
cancelImg.SetWidescreen(Settings.widescreen);
}
GuiButton cancelBtn(&cancelImg, &cancelImg, 2, 4, 0, -45, &trigA, btnSoundOver, btnSoundClick2, 1);
cancelBtn.SetLabel(&cancelTxt);
cancelBtn.SetState(STATE_SELECTED);
2010-09-24 02:48:03 +02:00
usleep(400000); // wait to see if progress flag changes soon
if (!showProgress) return;
promptWindow.Append(&dialogBoxImg);
promptWindow.Append(&progressbarEmptyImg);
promptWindow.Append(&progressbarImg);
promptWindow.Append(&progressbarOutlineImg);
promptWindow.Append(&prTxt);
promptWindow.Append(&prsTxt);
if (title) promptWindow.Append(&titleTxt);
promptWindow.Append(&msg1Txt);
promptWindow.Append(&msg2Txt);
2010-09-24 02:48:03 +02:00
if (showTime) promptWindow.Append(&timeTxt);
if (showSize)
{
2010-09-24 02:48:03 +02:00
promptWindow.Append(&sizeTxt);
promptWindow.Append(&speedTxt);
}
if(AbortCallback)
promptWindow.Append(&cancelBtn);
HaltGui();
2010-09-24 02:48:03 +02:00
promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50);
mainWindow->SetState(STATE_DISABLED);
mainWindow->Append(&promptWindow);
mainWindow->ChangeFocus(&promptWindow);
ResumeGui();
2010-09-24 02:48:03 +02:00
while (promptWindow.GetEffect() > 0)
usleep(100);
int tmp;
2010-09-24 02:48:03 +02:00
while (showProgress)
{
usleep(100000);
GameInstallProgress();
2010-09-24 02:48:03 +02:00
if (changed)
{
2009-10-20 01:09:27 +02:00
changed = false;
2010-09-24 02:48:03 +02:00
tmp = static_cast<int> (progressbarImg.GetWidth() * progressDone);
2010-10-27 16:45:27 +02:00
if (Settings.widescreen && Settings.wsprompt)
2010-09-24 02:48:03 +02:00
progressbarImg.SetSkew(0, 0, static_cast<int> (progressbarImg.GetWidth() * progressDone * 0.8)
- progressbarImg.GetWidth(), 0, static_cast<int> (progressbarImg.GetWidth() * progressDone
* 0.8) - progressbarImg.GetWidth(), 0, 0, 0);
else progressbarImg.SetSkew(0, 0, static_cast<int> (progressbarImg.GetWidth() * progressDone)
- progressbarImg.GetWidth(), 0, static_cast<int> (progressbarImg.GetWidth() * progressDone)
- progressbarImg.GetWidth(), 0, 0, 0);
2009-10-20 01:09:27 +02:00
2010-09-24 02:48:03 +02:00
prTxt.SetTextf("%.2f", progressDone);
2010-09-24 02:48:03 +02:00
if (showSize)
{
2010-09-24 02:48:03 +02:00
sizeTxt.SetText(progressSizeLeft);
speedTxt.SetText(progressSpeed);
2009-10-20 01:09:27 +02:00
}
2010-09-24 02:48:03 +02:00
if (showTime) timeTxt.SetText(progressTime);
2009-10-20 01:09:27 +02:00
if (progressMsg1) msg1Txt.SetText(progressMsg1);
if (progressMsg2) msg2Txt.SetText(progressMsg2);
}
if(cancelBtn.GetState() == STATE_CLICKED)
{
if(AbortCallback) AbortCallback();
cancelBtn.ResetState();
2009-10-20 01:09:27 +02:00
}
}
2010-09-24 02:48:03 +02:00
promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50);
while (promptWindow.GetEffect() > 0)
usleep(100);
HaltGui();
2010-09-24 02:48:03 +02:00
mainWindow->Remove(&promptWindow);
mainWindow->SetState(STATE_DEFAULT);
ResumeGui();
}
/****************************************************************************
* ProgressThread
2010-09-24 02:48:03 +02:00
***************************************************************************/
2010-09-24 02:48:03 +02:00
static void * ProgressThread(void *arg)
{
2010-09-24 02:48:03 +02:00
while (1)
{
2010-09-24 02:48:03 +02:00
if (!showProgress) LWP_SuspendThread(progressthread);
2010-09-24 02:48:03 +02:00
ProgressWindow(progressTitle, progressMsg1, progressMsg2);
usleep(100);
}
return NULL;
}
/****************************************************************************
* ProgressStop
***************************************************************************/
void ProgressStop()
{
showProgress = 0;
strcpy(progressTitle, "");
progressMsg1 = NULL;
progressMsg2 = NULL;
gameinstalltotal = -1;
// wait for thread to finish
2010-09-24 02:48:03 +02:00
while (!LWP_ThreadIsSuspended(progressthread))
usleep(100);
}
/****************************************************************************
* ShowProgress
*
* Callbackfunction for updating the progress values
* Use this function as standard callback
***************************************************************************/
void ShowProgress(const char *title, const char *msg1, const char *msg2, f32 done, f32 total, bool swSize, bool swTime)
{
2010-09-24 02:48:03 +02:00
if (total <= 0)
return;
2010-09-24 02:48:03 +02:00
else if (done > total) done = total;
showSize = swSize;
showTime = swTime;
2010-09-24 02:48:03 +02:00
if (title) strlcpy(progressTitle, title, sizeof(progressTitle));
progressMsg1 = msg1;
progressMsg2 = msg2;
static u32 expected;
u32 elapsed, h, m, s, speed = 0;
2010-09-24 02:48:03 +02:00
if (!done)
{
2010-09-24 02:48:03 +02:00
start = time(0);
expected = 300;
2010-09-24 02:48:03 +02:00
LWP_ResumeThread(progressthread);
}
//Elapsed time
2010-09-24 02:48:03 +02:00
elapsed = time(0) - start;
//Calculate speed in KB/s
2010-09-24 02:48:03 +02:00
if (elapsed > 0) speed = done / (elapsed * KB_SIZE);
2010-09-24 02:48:03 +02:00
if (done != total)
{
//Expected time
2010-09-24 02:48:03 +02:00
if (elapsed) expected = (expected * 3 + elapsed * total / done) / 4;
//Remaining time
2010-09-24 02:48:03 +02:00
elapsed = (expected > elapsed) ? (expected - elapsed) : 0;
}
//Calculate time values
2010-09-24 02:48:03 +02:00
h = elapsed / 3600;
m = (elapsed / 60) % 60;
s = elapsed % 60;
2010-09-24 02:48:03 +02:00
if (swTime == true)
{
2010-09-24 02:48:03 +02:00
snprintf(progressTime, sizeof(progressTime), "%s %d:%02d:%02d", tr( "Time left:" ), h, m, s);
}
2010-09-24 02:48:03 +02:00
if (swSize == true)
{
2010-09-24 02:48:03 +02:00
if (total < MB_SIZE)
snprintf(progressSizeLeft, sizeof(progressSizeLeft), "%0.2fKB/%0.2fKB", done * done / total / KB_SIZE,
total / KB_SIZE);
else if (total > MB_SIZE && total < GB_SIZE)
snprintf(progressSizeLeft, sizeof(progressSizeLeft), "%0.2fMB/%0.2fMB", done * done / total / MB_SIZE,
total / MB_SIZE);
else snprintf(progressSizeLeft, sizeof(progressSizeLeft), "%0.2fGB/%0.2fGB", done * done / total / GB_SIZE,
total / GB_SIZE);
snprintf(progressSpeed, sizeof(progressSpeed), "%dKB/s", speed);
}
showProgress = 1;
progressDone = 100.0 * done / total;
2009-10-20 01:09:27 +02:00
changed = true;
}
/****************************************************************************
* ProgressSetAbortCallback
*
* Set a callback for the cancel button
***************************************************************************/
void ProgressSetAbortCallback(ProgressAbortCallback callback)
{
AbortCallback = callback;
}
/****************************************************************************
* InitProgressThread
*
* Startup Progressthread in idle prio
***************************************************************************/
void InitProgressThread()
{
2010-09-24 02:48:03 +02:00
LWP_CreateThread(&progressthread, ProgressThread, NULL, NULL, 16384, 80);
}
/****************************************************************************
* ExitProgressThread
*
* Shutdown Progressthread
***************************************************************************/
void ExitProgressThread()
{
2010-09-24 02:48:03 +02:00
LWP_JoinThread(progressthread, NULL);
progressthread = LWP_THREAD_NULL;
}