DlgDownload.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: /Commando/Code/Commando/DlgDownload.cpp $
  22. *
  23. * DESCRIPTION
  24. * File download dialog.
  25. *
  26. * PROGRAMMER
  27. * Denzil E. Long, Jr.
  28. * $Author: Steve_t $
  29. *
  30. * VERSION INFO
  31. * $Revision: 11 $
  32. * $Modtime: 1/12/02 2:53p $
  33. *
  34. ******************************************************************************/
  35. #include "DlgDownload.h"
  36. #include "DlgMessageBox.h"
  37. #include "DlgRestart.h"
  38. #include "Resource.h"
  39. #include <WWUI\ProgressCtrl.h>
  40. #include "String_IDs.h"
  41. #include <WWTranslateDB\TranslateDB.h>
  42. #include <WWDebug\WWDebug.h>
  43. #include "mainloop.h"
  44. #include "consolemode.h"
  45. #ifdef _MSC_VER
  46. #pragma warning (push,3)
  47. #endif
  48. #include "systimer.h"
  49. #ifdef _MSC_VER
  50. #pragma warning (pop)
  51. #endif
  52. using namespace WWOnline;
  53. static void PrintableSize(unsigned long size, WideStringClass& printable);
  54. static void PrintableTime(unsigned long seconds, WideStringClass& printable);
  55. bool DlgDownload::mQuietMode = false;
  56. /******************************************************************************
  57. *
  58. * NAME
  59. * DlgDownload::DoDialog
  60. *
  61. * DESCRIPTION
  62. * Start download dialog
  63. *
  64. * INPUTS
  65. * Title - Dialog title
  66. * Files - List of files to download
  67. *
  68. * RESULT
  69. * Success - True if dialog successfully started.
  70. *
  71. ******************************************************************************/
  72. bool DlgDownload::DoDialog(const WCHAR* title, const DownloadList& files, bool quiet)
  73. {
  74. if (!files.empty())
  75. {
  76. mQuietMode = quiet;
  77. DlgDownload* popup = new DlgDownload;
  78. if (popup)
  79. {
  80. if (popup->FinalizeCreate(files))
  81. {
  82. popup->Start_Dialog();
  83. popup->Set_Title(title);
  84. }
  85. popup->Release_Ref();
  86. }
  87. return (popup != NULL);
  88. }
  89. return false;
  90. }
  91. /******************************************************************************
  92. *
  93. * NAME
  94. * DlgDownload::DlgDownload
  95. *
  96. * DESCRIPTION
  97. * Constructor
  98. *
  99. * INPUTS
  100. * NONE
  101. *
  102. * RESULT
  103. * NONE
  104. *
  105. ******************************************************************************/
  106. DlgDownload::DlgDownload() :
  107. PopupDialogClass(IDD_WOL_DOWNLOAD),
  108. mDownloading(false)
  109. {
  110. WWDEBUG_SAY(("DlgDownload: Instantiated\n"));
  111. }
  112. /******************************************************************************
  113. *
  114. * NAME
  115. * DlgDownload::~DlgDownload
  116. *
  117. * DESCRIPTION
  118. * Destructor
  119. *
  120. * INPUTS
  121. * NONE
  122. *
  123. * RESULT
  124. * NONE
  125. *
  126. ******************************************************************************/
  127. DlgDownload::~DlgDownload()
  128. {
  129. WWDEBUG_SAY(("DlgDownload: Destructing\n"));
  130. }
  131. /******************************************************************************
  132. *
  133. * NAME
  134. * DlgDownload::FinalizeCreate
  135. *
  136. * DESCRIPTION
  137. * Finalize the dialog creation.
  138. *
  139. * INPUTS
  140. * Files - List of files to download.
  141. *
  142. * RESULT
  143. * True if successful.
  144. *
  145. ******************************************************************************/
  146. bool DlgDownload::FinalizeCreate(const DownloadList& files)
  147. {
  148. mWait = DownloadWait::Create(files);
  149. return mWait.IsValid();
  150. }
  151. /******************************************************************************
  152. *
  153. * NAME
  154. * DlgDownload::On_Init_Dialog
  155. *
  156. * DESCRIPTION
  157. * One time dialog initialization.
  158. *
  159. * INPUTS
  160. * NONE
  161. *
  162. * RESULT
  163. * NONE
  164. *
  165. ******************************************************************************/
  166. void DlgDownload::On_Init_Dialog(void)
  167. {
  168. // Set estimated time and read / total
  169. WideStringClass text(0, true);
  170. text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_TIME), 0, 0, 0);
  171. Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
  172. // Update transfer rate.
  173. text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE), 0);
  174. Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
  175. // Start the wait condition
  176. mWait->SetCallback(DlgDownload::HandleCallback, (unsigned long)this);
  177. mWait->WaitBeginning();
  178. PopupDialogClass::On_Init_Dialog();
  179. }
  180. /******************************************************************************
  181. *
  182. * NAME
  183. * DlgDownload::On_Command
  184. *
  185. * DESCRIPTION
  186. * Process command message
  187. *
  188. * INPUTS
  189. * Ctrl - ID of control
  190. * Message -
  191. * Param -
  192. *
  193. * RESULT
  194. * NONE
  195. *
  196. ******************************************************************************/
  197. void DlgDownload::On_Command(int ctrl, int message, DWORD param)
  198. {
  199. if (ctrl == IDCANCEL)
  200. {
  201. WWDEBUG_SAY(("DlgDownload: User Aborted\n"));
  202. mWait->EndWait(WaitCondition::UserCancel, TRANSLATE(IDS_WOL_CANCELED));
  203. }
  204. PopupDialogClass::On_Command(ctrl, message, param);
  205. }
  206. /******************************************************************************
  207. *
  208. * NAME
  209. * DlgDownload::On_Periodic
  210. *
  211. * DESCRIPTION
  212. *
  213. * INPUTS
  214. * NONE
  215. *
  216. * RESULT
  217. * NONE
  218. *
  219. ******************************************************************************/
  220. void DlgDownload::On_Periodic(void)
  221. {
  222. PopupDialogClass::On_Periodic();
  223. // Check the status of the wait condition
  224. WaitCondition::WaitResult waitStatus = mWait->GetResult();
  225. // If we are no longer waiting then process the result.
  226. if (waitStatus != WaitCondition::Waiting)
  227. {
  228. if (waitStatus == WaitCondition::ConditionMet)
  229. {
  230. if (mQuietMode)
  231. {
  232. ConsoleBox.Print("Restarting....\n");
  233. Stop_Main_Loop(RESTART_EXITCODE);
  234. }
  235. else
  236. {
  237. DlgRestart::DoDialog();
  238. }
  239. }
  240. else
  241. {
  242. // If the download was aborted or errored then show a message dialog
  243. // describing the failure.
  244. DlgMsgBox::DoDialog(TRANSLATE(IDS_WOL_DOWNLOADERROR), mWait->GetResultText());
  245. }
  246. End_Dialog();
  247. }
  248. }
  249. /******************************************************************************
  250. *
  251. * NAME
  252. * DlgDownload::UpdateProgress
  253. *
  254. * DESCRIPTION
  255. *
  256. * INPUTS
  257. *
  258. * RESULT
  259. * NONE
  260. *
  261. ******************************************************************************/
  262. void DlgDownload::UpdateProgress(DownloadEvent& event)
  263. {
  264. const RefPtr<Download>& download = event.GetDownload();
  265. switch (event.GetEvent())
  266. {
  267. case DownloadEvent::DOWNLOAD_STATUS:
  268. Set_Dlg_Item_Text(IDC_STATUSTEXT, download->GetStatusText());
  269. break;
  270. case DownloadEvent::DOWNLOAD_PROGRESS:
  271. {
  272. int read = 0;
  273. int size = 0;
  274. int elapsed = 0;
  275. int remaining = 0;
  276. download->GetProgress(read, size, elapsed, remaining);
  277. if (ConsoleBox.Is_Exclusive())
  278. {
  279. if (!mDownloading)
  280. {
  281. mStartTime = TIMEGETTIME();
  282. mDownloading = true;
  283. }
  284. // Calculate the transfer rate
  285. unsigned long transferRate = read;
  286. unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
  287. if (elapsedTime > 0)
  288. {
  289. transferRate = (read / elapsedTime);
  290. }
  291. ConsoleBox.Print("Got %d Kb of %d at %d Kb per second \r", read/1024, size/1024, transferRate / 1024);
  292. }
  293. else
  294. {
  295. // Update progress bar
  296. ProgressCtrlClass* progress = (ProgressCtrlClass*)Get_Dlg_Item(IDC_PROGRESS);
  297. if (progress)
  298. {
  299. // If we have just begun downloading then set the progress bar range
  300. // for the size of the new file.
  301. if (!mDownloading)
  302. {
  303. progress->Set_Range(0, size);
  304. mStartTime = TIMEGETTIME();
  305. mDownloading = true;
  306. }
  307. progress->Set_Position(read);
  308. }
  309. //-----------------------------------------------------------------------
  310. // Update download statistics
  311. //-----------------------------------------------------------------------
  312. // Calculate the transfer rate
  313. unsigned long transferRate = read;
  314. unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
  315. if (elapsedTime > 0)
  316. {
  317. transferRate = (read / elapsedTime);
  318. }
  319. // Update transfer rate.
  320. WideStringClass sizetext(64, true);
  321. PrintableSize(transferRate, sizetext);
  322. WideStringClass text(0, true);
  323. text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_PER_SEC), (const WCHAR*)sizetext);
  324. Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
  325. // Calculate estimated time based on the current transfer rate.
  326. unsigned long estimatedTime = 0;
  327. if (transferRate > 0)
  328. {
  329. estimatedTime = ((size - read) / transferRate);
  330. }
  331. // Update estimated time and read / total
  332. WideStringClass timetext(64,true);
  333. PrintableTime(estimatedTime, timetext);
  334. WideStringClass readtext(64, true);
  335. PrintableSize(read, readtext);
  336. PrintableSize(size, sizetext);
  337. text.Format(TRANSLATE(IDS_MENU_TRANSFER_TIME_LEFT),
  338. (const WCHAR*)timetext, (const WCHAR*)readtext, (const WCHAR*)sizetext);
  339. Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
  340. }
  341. }
  342. break;
  343. case DownloadEvent::DOWNLOAD_BEGIN:
  344. if (ConsoleBox.Is_Exclusive())
  345. {
  346. ConsoleBox.Print("\n");
  347. }
  348. break;
  349. case DownloadEvent::DOWNLOAD_END:
  350. if (ConsoleBox.Is_Exclusive())
  351. {
  352. ConsoleBox.Print("\nDownload complete\n");
  353. }
  354. WWDEBUG_SAY(("DlgDownload: Successful '%s' Elapsed time: %ld ms\n",
  355. download->GetFilename(), (TIMEGETTIME() - mStartTime)));
  356. mDownloading = false;
  357. break;
  358. case DownloadEvent::DOWNLOAD_STOPPED:
  359. WWDEBUG_SAY(("DlgDownload: Stopped '%s'\n", download->GetFilename()));
  360. mDownloading = false;
  361. break;
  362. case DownloadEvent::DOWNLOAD_ERROR:
  363. WWDEBUG_SAY(("DlgDownload: Error '%s'\n", download->GetFilename()));
  364. mDownloading = false;
  365. break;
  366. default:
  367. break;
  368. }
  369. }
  370. /******************************************************************************
  371. *
  372. * NAME
  373. * DlgDownload::HandleCallback
  374. *
  375. * DESCRIPTION
  376. *
  377. * INPUTS
  378. *
  379. * RESULT
  380. * NONE
  381. *
  382. ******************************************************************************/
  383. void DlgDownload::HandleCallback(DownloadEvent& event, unsigned long userdata)
  384. {
  385. DlgDownload* dialog = (DlgDownload*)userdata;
  386. if (dialog)
  387. {
  388. dialog->UpdateProgress(event);
  389. }
  390. }
  391. /******************************************************************************
  392. *
  393. * NAME
  394. * PrintableSize
  395. *
  396. * DESCRIPTION
  397. * Get filesize in a printable format.
  398. *
  399. * INPUTS
  400. * Size -
  401. *
  402. * RESULT
  403. * NONE
  404. *
  405. ******************************************************************************/
  406. void PrintableSize(unsigned long size, WideStringClass& printable)
  407. {
  408. float value = ((float)size / (float)(1024 * 1024));
  409. if (value >= 1.0)
  410. {
  411. printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MB_FORMAT), value);
  412. return;
  413. }
  414. value = ((float)size / 1024.0);
  415. if (value >= 1.0)
  416. {
  417. printable.Format(TRANSLATE(IDS_MENU_TRANSFER_KB_FORMAT), value);
  418. return;
  419. }
  420. printable.Format(TRANSLATE(IDS_MENU_TRANSFER_BYTE_FORMAT), size);
  421. }
  422. /******************************************************************************
  423. *
  424. * NAME
  425. * PrintableTime
  426. *
  427. * DESCRIPTION
  428. * Get time in a printable format.
  429. *
  430. * INPUTS
  431. * Size -
  432. *
  433. * RESULT
  434. * NONE
  435. *
  436. ******************************************************************************/
  437. void PrintableTime(unsigned long time, WideStringClass& printable)
  438. {
  439. unsigned long minutes = (time / 60);
  440. unsigned long seconds = (time % 60);
  441. if (minutes > 0)
  442. {
  443. printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MIN_SEC_FORMAT), minutes, seconds);
  444. }
  445. else
  446. {
  447. seconds = max<unsigned long>(seconds, 1);
  448. printable.Format(TRANSLATE(IDS_MENU_TRANSFER_SEC_FORMAT), seconds);
  449. }
  450. }