/* ** 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 . */ /****************************************************************************** * * 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 #include "String_IDs.h" #include #include #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 = 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(seconds, 1); printable.Format(TRANSLATE(IDS_MENU_TRANSFER_SEC_FORMAT), seconds); } }