2 Copyright © 2009, The AROS Development Team. All rights reserved.
6 /* Process this class after all the base
7 * custom classes have been created
9 #define ZUNE_CUSTOMCLASS_PASS 101
11 #include <proto/alib.h>
12 #include <proto/exec.h>
13 #include <proto/muimaster.h>
14 #include <proto/asl.h>
15 #include <libraries/mui.h>
16 #include <libraries/asl.h>
17 #include <proto/intuition.h>
18 #include <proto/alib.h>
19 #include <proto/utility.h>
20 #include <proto/dos.h>
23 #include <aros/debug.h>
24 #include <aros/symbolsets.h>
25 #include <zune/customclasses.h>
27 #include "DownloadDelegateZune.h"
28 #include "browserpreferences.h"
30 #include "downloadmanager_private.h"
31 #include "downloadmanager.h"
35 enum { DOWNLOAD_CREATED
, DOWNLOAD_ACTIVE
, DOWNLOAD_ERROR
, DOWNLOAD_FINISHED
, DOWNLOAD_DESTROYED
};
37 static IPTR
ManagerDisplayFunc(struct Hook
*hook
, char **columns
, struct Download
*download
)
41 columns
[0] = (char*) _(MSG_DownloadFileName
);
42 columns
[1] = (char*) _(MSG_DownloadFileSize
);
43 columns
[2] = (char*) _(MSG_DownloadProgress
);
44 columns
[3] = (char*) _(MSG_DownloadSpeed
);
45 columns
[4] = (char*) _(MSG_DownloadState
);
49 columns
[0] = (download
->filename
? download
->filename
: (char*) _(MSG_UnknownFileName
));
50 columns
[1] = (download
->filesize
? download
->filesize
: (char*) _(MSG_UnknownFileSize
));
51 columns
[2] = download
->progress
;
52 columns
[3] = (download
->speed
? download
->speed
: (char*) _(MSG_UnknownDownloadSpeed
));
53 switch(download
->state
)
55 case DOWNLOAD_CREATED
:
56 columns
[4] = (char*) _(MSG_DownloadState_Starting
);
59 columns
[4] = (char*) _(MSG_DownloadState_Active
);
62 columns
[4] = (char*) _(MSG_DownloadState_Failed
);
64 case DOWNLOAD_FINISHED
:
65 columns
[4] = (char*) _(MSG_DownloadState_Finished
);
72 D(bug("displaying %s | %s | %s\n", columns
[0], columns
[1], columns
[2]));
76 static IPTR
ManagerDestroyFunc(struct Hook
*hook
, APTR pool
, struct Download
*download
)
81 download
->state
= DOWNLOAD_DESTROYED
;
82 FreeVec(download
->filename
);
83 FreeVec(download
->filesize
);
84 FreeVec(download
->speed
);
85 Remove((struct Node
*) download
);
91 static IPTR
CancelFunc(struct Hook
*hook
, Object
*list
, void *data
)
94 get(list
, MUIA_List_Active
, &active
);
96 if(active
== MUIV_List_Active_Off
)
99 struct Download
*download
= NULL
;
100 DoMethod(list
, MUIM_List_GetEntry
, active
, &download
);
104 Object
*manager
= download
->manager
;
105 DoMethod(manager
, MUIM_DownloadDelegate_CancelDownload
, (IPTR
) download
->identifier
);
106 DoMethod(list
, MUIM_List_Remove
, active
);
107 DoMethod(manager
, MUIM_DownloadManager_UpdateInterface
);
113 static IPTR
ClearFinishedFunc(struct Hook
*hook
, Object
*list
, void *data
)
116 for(i
= XGET(list
, MUIA_List_Entries
) - 1; i
>= 0; i
--)
118 struct Download
*download
= NULL
;
119 DoMethod(list
, MUIM_List_GetEntry
, i
, &download
);
122 if(download
->state
== DOWNLOAD_FINISHED
)
123 DoMethod(list
, MUIM_List_Remove
, i
);
129 static struct Download
*GetDownload(struct DownloadManager_DATA
*manager
, void *downid
)
131 struct Download
*download
;
132 ForeachNode(&manager
->downloads
, download
)
134 if(download
->identifier
== downid
)
140 IPTR
DownloadManager__OM_NEW(struct IClass
*cl
, Object
*self
, struct opSet
*msg
)
142 Object
*list
= NULL
, *bt_cancel
, *bt_clearFinished
;
143 Object
*preferences
= NULL
;
144 struct TagItem
*tag
, *tags
;
146 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
)); )
150 case MUIA_DownloadManager_Preferences
:
151 preferences
= (Object
*) tag
->ti_Data
;
154 continue; /* Don't supress non-processed tags */
156 tag
->ti_Tag
= TAG_IGNORE
;
160 D(bug("DownloadManager: No preferences given\n"));
164 self
= (Object
*) DoSuperNewTags
168 MUIA_Window_Title
, _(MSG_DownloadManager_Title
),
169 WindowContents
, (IPTR
)(VGroup
,
174 Child
, (IPTR
)(ListviewObject
,
175 MUIA_Listview_List
, (IPTR
)(list
= ListObject
,
176 MUIA_List_Format
, (IPTR
)"BAR,BAR,BAR,BAR,",
177 MUIA_List_Title
, TRUE
,
180 Child
, (IPTR
)(HGroup
,
181 Child
, (IPTR
)(bt_cancel
= SimpleButton(_(MSG_DownloadManager_Cancel
))),
182 Child
, (IPTR
)(bt_clearFinished
= SimpleButton(_(MSG_DownloadManager_ClearFinished
))),
185 TAG_MORE
, (IPTR
) msg
->ops_AttrList
189 D(bug("DownloadManager: Could not create self\n"));
193 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, self
);
195 NewList(&manager
->downloads
);
196 manager
->displayHook
.h_Entry
= HookEntry
;
197 manager
->displayHook
.h_SubEntry
= (HOOKFUNC
) ManagerDisplayFunc
;
198 manager
->destroyHook
.h_Entry
= HookEntry
;
199 manager
->destroyHook
.h_SubEntry
= (HOOKFUNC
) ManagerDestroyFunc
;
200 manager
->cancelHook
.h_Entry
= HookEntry
;
201 manager
->cancelHook
.h_SubEntry
= (HOOKFUNC
) CancelFunc
;
202 manager
->clearFinishedHook
.h_Entry
= HookEntry
;
203 manager
->clearFinishedHook
.h_SubEntry
= (HOOKFUNC
) ClearFinishedFunc
;
204 manager
->list
= list
;
205 manager
->preferences
= preferences
;
206 manager
->bt_cancel
= bt_cancel
;
208 set(bt_cancel
, MUIA_Disabled
, TRUE
);
209 set(list
, MUIA_List_DisplayHook
, &manager
->displayHook
);
210 set(list
, MUIA_List_DestructHook
, &manager
->destroyHook
);
212 /* Close window with close gadget */
213 DoMethod(self
, MUIM_Notify
, MUIA_Window_CloseRequest
, (IPTR
) TRUE
,
214 (IPTR
) self
, (IPTR
) 3,
215 MUIM_Set
, MUIA_Window_Open
, (IPTR
) FALSE
);
217 DoMethod(bt_cancel
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
218 (IPTR
) list
, (IPTR
) 3,
219 MUIM_CallHook
, &manager
->cancelHook
, NULL
);
221 DoMethod(bt_clearFinished
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
222 (IPTR
) list
, (IPTR
) 3,
223 MUIM_CallHook
, &manager
->clearFinishedHook
, NULL
);
225 DoMethod(list
, MUIM_Notify
, MUIA_List_Active
, MUIV_EveryTime
,
226 (IPTR
) self
, (IPTR
) 1,
227 MUIM_DownloadManager_UpdateInterface
);
232 IPTR
DownloadManager__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
234 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
236 /* Destroy all downloads, so they won't send notifications anymore */
237 DoMethod(manager
->list
, MUIM_List_Clear
);
239 return DoSuperMethodA(cl
,obj
,msg
);
242 IPTR
DownloadManager__MUIM_DownloadDelegate_DidBeginDownload(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DidBeginDownload
* message
)
244 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
246 struct Download
*download
= (struct Download
*) AllocVec(sizeof(struct Download
), MEMF_ANY
| MEMF_CLEAR
);
247 download
->identifier
= message
->download
;
248 download
->state
= DOWNLOAD_CREATED
;
249 download
->sizeTotal
= -1;
250 download
->sizeDownloaded
= 0;
251 download
->manager
= obj
;
252 download
->filename
= NULL
;
253 download
->filesize
= NULL
;
254 download
->speed
= NULL
;
255 download
->speedMeasureTime
= time(NULL
);
256 download
->listRedrawTime
= time(NULL
);
257 download
->speedSizeDownloaded
= 0;
258 sprintf(download
->progress
, "%ld %%", (long)0);
263 AddHead(&manager
->downloads
, (struct Node
*) download
);
265 DoMethod(manager
->list
, MUIM_List_InsertSingle
, download
, 0);
266 SetAttrs(obj
, MUIA_Window_Open
, TRUE
);
267 DoMethod(obj
, MUIM_DownloadManager_UpdateInterface
);
272 IPTR
DownloadManager__MUIM_DownloadDelegate_DidFinishDownload(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DidFinishDownload
* message
)
274 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
276 struct Download
*download
= GetDownload(manager
, message
->download
);
280 download
->state
= DOWNLOAD_FINISHED
;
282 sprintf(download
->progress
, "%ld %%", (long) (download
->sizeTotal
> 0 ? 100 * download
->sizeDownloaded
/ download
->sizeTotal
: 0));
284 /* Activate finished entry */
288 struct Download
*down
;
289 DoMethod(manager
->list
, MUIM_List_GetEntry
, i
, &down
);
295 set(manager
->list
, MUIA_List_Active
, i
);
301 SetAttrs(obj
, MUIA_Window_Open
, TRUE
);
302 DoMethod(manager
->list
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
303 DoMethod(obj
, MUIM_DownloadManager_UpdateInterface
);
308 IPTR
DownloadManager__MUIM_DownloadDelegate_DidFailWithError(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DidFailWithError
* message
)
310 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
312 struct Download
*download
= GetDownload(manager
, message
->download
);
316 download
->state
= DOWNLOAD_ERROR
;
318 /* Activate failed entry */
322 struct Download
*down
;
323 DoMethod(manager
->list
, MUIM_List_GetEntry
, i
, &down
);
329 set(manager
->list
, MUIA_List_Active
, i
);
334 SetAttrs(obj
, MUIA_Window_Open
, TRUE
);
335 DoMethod(manager
->list
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
336 DoMethod(obj
, MUIM_DownloadManager_UpdateInterface
);
341 IPTR
DownloadManager__MUIM_DownloadDelegate_DecideDestinationWithSuggestedFilename(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DecideDestinationWithSuggestedFilename
* message
)
343 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
344 char *destination
= NULL
;
346 struct Download
*download
= GetDownload(manager
, message
->download
);
350 if(download
->filename
)
351 FreeVec(download
->filename
);
353 char *filename
= message
->filename
;
355 const char *prefix
= (const char*) XGET(manager
->preferences
, MUIA_BrowserPreferences_DownloadDestination
);
356 if(strlen(filename
) == 0)
357 filename
= strdup(_(MSG_UnknownFileName
));
359 BOOL requestFileName
= XGET(manager
->preferences
, MUIA_BrowserPreferences_RequestDownloadedFileName
);
362 struct FileRequester
*fr
;
364 struct TagItem frtags
[] =
366 { ASLFR_TitleText
, (IPTR
)_(MSG_DownloadManager_RequestDownloadedFileTitle
) },
367 { ASLFR_InitialDrawer
, (IPTR
)prefix
},
368 { ASLFR_InitialFile
, (IPTR
)filename
},
369 { ASLFR_DoSaveMode
, (BOOL
)TRUE
},
373 if((fr
= (struct FileRequester
*) AllocAslRequest(ASL_FileRequest
, frtags
)))
375 if(AslRequest(fr
, NULL
))
377 download
->filename
= StrDup(fr
->fr_File
);
378 destination
= AllocVec(strlen(fr
->fr_Drawer
) + strlen(fr
->fr_File
) + 2, MEMF_ANY
);
379 strcpy(destination
, fr
->fr_Drawer
);
380 AddPart(destination
, fr
->fr_File
, strlen(fr
->fr_Drawer
) + strlen(fr
->fr_File
) + 2);
395 download
->filename
= StrDup(filename
);
396 destination
= AllocVec(strlen(filename
) + strlen(prefix
) + 2, MEMF_ANY
);
397 strcpy(destination
, prefix
);
398 AddPart(destination
, filename
, strlen(filename
) + strlen(prefix
) + 2);
401 D(bug("setting destination %s\n", destination
));
402 DoMethod(obj
, MUIM_DownloadDelegate_SetDestination
, download
->identifier
, destination
);
403 FreeVec(destination
);
405 if(destination
== NULL
)
407 // download is cancelled now, remove it
409 for(i
= XGET(manager
->list
, MUIA_List_Entries
) - 1; i
>= 0; i
--)
411 struct Download
*download_entry
= NULL
;
412 DoMethod(manager
->list
, MUIM_List_GetEntry
, i
, &download_entry
);
413 if(download
== download_entry
)
415 set(manager
->list
, MUIA_List_Active
, i
);
416 DoMethod(_app(obj
), MUIM_Application_PushMethod
, manager
->list
, 3, MUIM_CallHook
, &manager
->cancelHook
, NULL
);
422 DoMethod(manager
->list
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
427 IPTR
DownloadManager__MUIM_DownloadDelegate_DidReceiveExpectedContentLength(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DidReceiveExpectedContentLength
* message
)
429 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
431 struct Download
*download
= GetDownload(manager
, message
->download
);
435 download
->sizeTotal
= message
->length
;
437 if(download
->filesize
)
438 FreeVec(download
->filesize
);
443 if(download
->sizeTotal
< 1024)
445 template = "%.0lf b";
446 scaledsize
= download
->sizeTotal
;
448 else if(download
->sizeTotal
< 1024 * 1024)
450 template = "%.2lf kB";
451 scaledsize
= 1.0 * download
->sizeTotal
/ 1024;
455 template = "%.2lf MB";
456 scaledsize
= 1.0 * download
->sizeTotal
/ (1024 * 1024);
460 int length
= snprintf(&c
, 0, template, scaledsize
) + 1;
461 char *filesize
= AllocVec(length
, MEMF_ANY
);
464 snprintf(filesize
, length
, template, scaledsize
);
465 download
->filesize
= filesize
;
467 DoMethod(manager
->list
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
473 IPTR
DownloadManager__MUIM_DownloadDelegate_DidReceiveDataOfLength(Class
*cl
, Object
*obj
, struct MUIP_DownloadDelegate_DidReceiveDataOfLength
* message
)
475 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
477 D(bug("DownloadProgressed(%d)\n", message
->length
));
478 struct Download
*download
= GetDownload(manager
, message
->download
);
482 if(download
->state
== DOWNLOAD_CREATED
)
483 download
->state
= DOWNLOAD_ACTIVE
;
485 download
->sizeDownloaded
+= message
->length
;
487 time_t currentTime
= time(NULL
);
488 if(currentTime
> download
->speedMeasureTime
)
490 long long downloaded
= download
->sizeDownloaded
- download
->speedSizeDownloaded
;
491 download
->speedSizeDownloaded
= download
->sizeDownloaded
;
492 int elapsed
= currentTime
- download
->speedMeasureTime
;
493 download
->speedMeasureTime
= currentTime
;
496 FreeVec(download
->speed
);
501 if(downloaded
< 1024)
503 template = "%.0lf b/s";
504 scaledspeed
= downloaded
/ elapsed
;
506 else if(downloaded
< 1024 * 1024)
508 template = "%.2lf kB/s";
509 scaledspeed
= 1.0 * downloaded
/ (1024 * elapsed
);
513 template = "%.2lf MB/s";
514 scaledspeed
= 1.0 * downloaded
/ (1024 * 1024 * elapsed
);
518 int length
= snprintf(&c
, 0, template, scaledspeed
) + 1;
519 char *transferspeed
= AllocVec(length
, MEMF_ANY
);
522 snprintf(transferspeed
, length
, template, scaledspeed
);
523 download
->speed
= transferspeed
;
527 if(currentTime
> download
->listRedrawTime
)
529 download
->listRedrawTime
= currentTime
;
530 sprintf(download
->progress
, "%ld %%", (long) (download
->sizeTotal
> 0 ? 100 * download
->sizeDownloaded
/ download
->sizeTotal
: 0));
531 DoMethod(manager
->list
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
537 IPTR
DownloadManager__MUIM_DownloadManager_UpdateInterface(Class
*cl
, Object
*obj
, Msg message
)
539 struct DownloadManager_DATA
*manager
= (struct DownloadManager_DATA
*) INST_DATA(cl
, obj
);
540 LONG active
= XGET(manager
->list
, MUIA_List_Active
);
541 struct Download
*download
= NULL
;
543 if(active
== MUIV_List_Active_Off
)
545 set(manager
->bt_cancel
, MUIA_Disabled
, TRUE
);
549 DoMethod(manager
->list
, MUIM_List_GetEntry
, active
, &download
);
551 if(download
&& download
->state
== DOWNLOAD_ACTIVE
)
552 set(manager
->bt_cancel
, MUIA_Disabled
, FALSE
);
554 set(manager
->bt_cancel
, MUIA_Disabled
, TRUE
);
560 DownloadManager
, NULL
, NULL
, DownloadDelegate_CLASS
,
561 OM_NEW
, struct opSet
*,
563 MUIM_DownloadDelegate_DidBeginDownload
, struct MUIP_DownloadDelegate_DidBeginDownload
*,
564 MUIM_DownloadDelegate_DidFinishDownload
, struct MUIP_DownloadDelegate_DidFinishDownload
*,
565 MUIM_DownloadDelegate_DidFailWithError
, struct MUIP_DownloadDelegate_DidFailWithError
*,
566 MUIM_DownloadDelegate_DidReceiveExpectedContentLength
, struct MUIP_DownloadDelegate_DidReceiveExpectedContentLength
*,
567 MUIM_DownloadDelegate_DidReceiveDataOfLength
, struct MUIP_DownloadDelegate_DidReceiveDataOfLength
*,
568 MUIM_DownloadDelegate_DecideDestinationWithSuggestedFilename
, struct MUIP_DownloadDelegate_DecideDestinationWithSuggestedFilename
*,
569 MUIM_DownloadManager_UpdateInterface
, Msg