Initial commit of the HEAD branch of the ELinks CVS repository, as of
[elinks/images.git] / src / network / progress.c
blob1d248a610b3bc9515e2fa00140ae5211e0b9f7f7
1 /* Downloads progression stuff. */
2 /* $Id: progress.c,v 1.35 2005/09/09 07:27:48 zas Exp $ */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include "elinks.h"
10 #include "network/progress.h"
11 #include "util/error.h"
12 #include "util/memory.h"
13 #include "util/time.h"
15 #define SPD_DISP_TIME ((milliseconds_T) 100)
16 #define CURRENT_SPD_AFTER ((milliseconds_T) 100)
19 int
20 has_progress(struct progress *progress)
22 timeval_T current_speed_after;
24 timeval_from_milliseconds(&current_speed_after, CURRENT_SPD_AFTER);
26 return (timeval_cmp(&progress->elapsed, &current_speed_after) >= 0);
29 struct progress *
30 init_progress(off_t start)
32 struct progress *progress = mem_calloc(1, sizeof(*progress));
34 if (progress) {
35 progress->start = start;
36 progress->timer = TIMER_ID_UNDEF;
39 return progress;
42 void
43 done_progress(struct progress *progress)
45 mem_free(progress);
48 void
49 update_progress(struct progress *progress, off_t loaded, off_t size, off_t pos)
51 off_t bytes_delta;
52 timeval_T now, elapsed, dis_b_max, dis_b_interval;
54 timeval_now(&now);
55 timeval_sub(&elapsed, &progress->last_time, &now);
56 timeval_copy(&progress->last_time, &now);
58 progress->loaded = loaded;
59 bytes_delta = progress->loaded - progress->last_loaded;
60 progress->last_loaded = progress->loaded;
62 timeval_add_interval(&progress->elapsed, &elapsed);
64 timeval_add_interval(&progress->dis_b, &elapsed);
65 timeval_from_milliseconds(&dis_b_max, mult_ms(SPD_DISP_TIME, CURRENT_SPD_SEC));
66 timeval_from_milliseconds(&dis_b_interval, SPD_DISP_TIME);
68 while (timeval_cmp(&progress->dis_b, &dis_b_max) >= 0) {
69 progress->cur_loaded -= progress->data_in_secs[0];
70 memmove(progress->data_in_secs, progress->data_in_secs + 1,
71 sizeof(*progress->data_in_secs) * (CURRENT_SPD_SEC - 1));
72 progress->data_in_secs[CURRENT_SPD_SEC - 1] = 0;
73 timeval_sub_interval(&progress->dis_b, &dis_b_interval);
75 progress->data_in_secs[CURRENT_SPD_SEC - 1] += bytes_delta;
76 progress->cur_loaded += bytes_delta;
78 progress->current_speed = progress->cur_loaded / (CURRENT_SPD_SEC * ((long) SPD_DISP_TIME) / 1000);
80 progress->pos = pos;
81 progress->size = size;
82 if (progress->size != -1 && progress->size < progress->pos)
83 progress->size = progress->pos;
85 progress->average_speed = timeval_div_off_t(progress->loaded, &progress->elapsed);
86 if (progress->average_speed) /* Division by zero risk */
87 timeval_from_seconds(&progress->estimated_time,
88 (progress->size - progress->pos) / progress->average_speed);
90 install_timer(&progress->timer, SPD_DISP_TIME, progress->timer_func, progress->timer_func_data);
93 void
94 start_update_progress(struct progress *progress, void (*timer_func)(void *),
95 void *timer_func_data)
97 if (!progress->valid) {
98 struct progress tmp;
100 /* Just copy useful fields from invalid progress. */
101 memset(&tmp, 0, sizeof(tmp));
102 tmp.start = progress->start;
103 tmp.seek = progress->seek;
104 tmp.valid = 1;
106 memcpy(progress, &tmp, sizeof(*progress));
108 timeval_now(&progress->last_time);
109 progress->last_loaded = progress->loaded;
110 progress->timer_func = timer_func;
111 progress->timer_func_data = timer_func_data;