This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/DlgDownload.cpp

534 lines
12 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgDownload.cpp $
*
* DESCRIPTION
* File download dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Steve_t $
*
* VERSION INFO
* $Revision: 11 $
* $Modtime: 1/12/02 2:53p $
*
******************************************************************************/
#include "DlgDownload.h"
#include "DlgMessageBox.h"
#include "DlgRestart.h"
#include "Resource.h"
#include <WWUI\ProgressCtrl.h>
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <WWDebug\WWDebug.h>
#include "mainloop.h"
#include "consolemode.h"
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#include "systimer.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
using namespace WWOnline;
static void PrintableSize(unsigned long size, WideStringClass& printable);
static void PrintableTime(unsigned long seconds, WideStringClass& printable);
bool DlgDownload::mQuietMode = false;
/******************************************************************************
*
* NAME
* DlgDownload::DoDialog
*
* DESCRIPTION
* Start download dialog
*
* INPUTS
* Title - Dialog title
* Files - List of files to download
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgDownload::DoDialog(const WCHAR* title, const DownloadList& files, bool quiet)
{
if (!files.empty())
{
mQuietMode = quiet;
DlgDownload* popup = new DlgDownload;
if (popup)
{
if (popup->FinalizeCreate(files))
{
popup->Start_Dialog();
popup->Set_Title(title);
}
popup->Release_Ref();
}
return (popup != NULL);
}
return false;
}
/******************************************************************************
*
* NAME
* DlgDownload::DlgDownload
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgDownload::DlgDownload() :
PopupDialogClass(IDD_WOL_DOWNLOAD),
mDownloading(false)
{
WWDEBUG_SAY(("DlgDownload: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgDownload::~DlgDownload
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgDownload::~DlgDownload()
{
WWDEBUG_SAY(("DlgDownload: Destructing\n"));
}
/******************************************************************************
*
* NAME
* DlgDownload::FinalizeCreate
*
* DESCRIPTION
* Finalize the dialog creation.
*
* INPUTS
* Files - List of files to download.
*
* RESULT
* True if successful.
*
******************************************************************************/
bool DlgDownload::FinalizeCreate(const DownloadList& files)
{
mWait = DownloadWait::Create(files);
return mWait.IsValid();
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Init_Dialog
*
* DESCRIPTION
* One time dialog initialization.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Init_Dialog(void)
{
// Set estimated time and read / total
WideStringClass text(0, true);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_TIME), 0, 0, 0);
Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
// Update transfer rate.
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE), 0);
Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
// Start the wait condition
mWait->SetCallback(DlgDownload::HandleCallback, (unsigned long)this);
mWait->WaitBeginning();
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Command
*
* DESCRIPTION
* Process command message
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Command(int ctrl, int message, DWORD param)
{
if (ctrl == IDCANCEL)
{
WWDEBUG_SAY(("DlgDownload: User Aborted\n"));
mWait->EndWait(WaitCondition::UserCancel, TRANSLATE(IDS_WOL_CANCELED));
}
PopupDialogClass::On_Command(ctrl, message, param);
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Periodic
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Periodic(void)
{
PopupDialogClass::On_Periodic();
// Check the status of the wait condition
WaitCondition::WaitResult waitStatus = mWait->GetResult();
// If we are no longer waiting then process the result.
if (waitStatus != WaitCondition::Waiting)
{
if (waitStatus == WaitCondition::ConditionMet)
{
if (mQuietMode)
{
ConsoleBox.Print("Restarting....\n");
Stop_Main_Loop(RESTART_EXITCODE);
}
else
{
DlgRestart::DoDialog();
}
}
else
{
// If the download was aborted or errored then show a message dialog
// describing the failure.
DlgMsgBox::DoDialog(TRANSLATE(IDS_WOL_DOWNLOADERROR), mWait->GetResultText());
}
End_Dialog();
}
}
/******************************************************************************
*
* NAME
* DlgDownload::UpdateProgress
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::UpdateProgress(DownloadEvent& event)
{
const RefPtr<Download>& download = event.GetDownload();
switch (event.GetEvent())
{
case DownloadEvent::DOWNLOAD_STATUS:
Set_Dlg_Item_Text(IDC_STATUSTEXT, download->GetStatusText());
break;
case DownloadEvent::DOWNLOAD_PROGRESS:
{
int read = 0;
int size = 0;
int elapsed = 0;
int remaining = 0;
download->GetProgress(read, size, elapsed, remaining);
if (ConsoleBox.Is_Exclusive())
{
if (!mDownloading)
{
mStartTime = TIMEGETTIME();
mDownloading = true;
}
// Calculate the transfer rate
unsigned long transferRate = read;
unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
if (elapsedTime > 0)
{
transferRate = (read / elapsedTime);
}
ConsoleBox.Print("Got %d Kb of %d at %d Kb per second \r", read/1024, size/1024, transferRate / 1024);
}
else
{
// Update progress bar
ProgressCtrlClass* progress = (ProgressCtrlClass*)Get_Dlg_Item(IDC_PROGRESS);
if (progress)
{
// If we have just begun downloading then set the progress bar range
// for the size of the new file.
if (!mDownloading)
{
progress->Set_Range(0, size);
mStartTime = TIMEGETTIME();
mDownloading = true;
}
progress->Set_Position(read);
}
//-----------------------------------------------------------------------
// Update download statistics
//-----------------------------------------------------------------------
// Calculate the transfer rate
unsigned long transferRate = read;
unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
if (elapsedTime > 0)
{
transferRate = (read / elapsedTime);
}
// Update transfer rate.
WideStringClass sizetext(64, true);
PrintableSize(transferRate, sizetext);
WideStringClass text(0, true);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_PER_SEC), (const WCHAR*)sizetext);
Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
// Calculate estimated time based on the current transfer rate.
unsigned long estimatedTime = 0;
if (transferRate > 0)
{
estimatedTime = ((size - read) / transferRate);
}
// Update estimated time and read / total
WideStringClass timetext(64,true);
PrintableTime(estimatedTime, timetext);
WideStringClass readtext(64, true);
PrintableSize(read, readtext);
PrintableSize(size, sizetext);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_TIME_LEFT),
(const WCHAR*)timetext, (const WCHAR*)readtext, (const WCHAR*)sizetext);
Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
}
}
break;
case DownloadEvent::DOWNLOAD_BEGIN:
if (ConsoleBox.Is_Exclusive())
{
ConsoleBox.Print("\n");
}
break;
case DownloadEvent::DOWNLOAD_END:
if (ConsoleBox.Is_Exclusive())
{
ConsoleBox.Print("\nDownload complete\n");
}
WWDEBUG_SAY(("DlgDownload: Successful '%s' Elapsed time: %ld ms\n",
download->GetFilename(), (TIMEGETTIME() - mStartTime)));
mDownloading = false;
break;
case DownloadEvent::DOWNLOAD_STOPPED:
WWDEBUG_SAY(("DlgDownload: Stopped '%s'\n", download->GetFilename()));
mDownloading = false;
break;
case DownloadEvent::DOWNLOAD_ERROR:
WWDEBUG_SAY(("DlgDownload: Error '%s'\n", download->GetFilename()));
mDownloading = false;
break;
default:
break;
}
}
/******************************************************************************
*
* NAME
* DlgDownload::HandleCallback
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::HandleCallback(DownloadEvent& event, unsigned long userdata)
{
DlgDownload* dialog = (DlgDownload*)userdata;
if (dialog)
{
dialog->UpdateProgress(event);
}
}
/******************************************************************************
*
* NAME
* PrintableSize
*
* DESCRIPTION
* Get filesize in a printable format.
*
* INPUTS
* Size -
*
* RESULT
* NONE
*
******************************************************************************/
void PrintableSize(unsigned long size, WideStringClass& printable)
{
float value = ((float)size / (float)(1024 * 1024));
if (value >= 1.0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MB_FORMAT), value);
return;
}
value = ((float)size / 1024.0);
if (value >= 1.0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_KB_FORMAT), value);
return;
}
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_BYTE_FORMAT), size);
}
/******************************************************************************
*
* NAME
* PrintableTime
*
* DESCRIPTION
* Get time in a printable format.
*
* INPUTS
* Size -
*
* RESULT
* NONE
*
******************************************************************************/
void PrintableTime(unsigned long time, WideStringClass& printable)
{
unsigned long minutes = (time / 60);
unsigned long seconds = (time % 60);
if (minutes > 0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MIN_SEC_FORMAT), minutes, seconds);
}
else
{
seconds = max<unsigned long>(seconds, 1);
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_SEC_FORMAT), seconds);
}
}