Call decompress_data only for compressed data.
[elinks/elinks-j605.git] / src / network / progress.c
blobcf16615e8b1886f60547a91273a606b866b1547a
1 /* Downloads progression stuff. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "network/progress.h"
10 #include "util/error.h"
11 #include "util/memory.h"
12 #include "util/time.h"
14 #define SPD_DISP_TIME ((milliseconds_T) 100)
15 #define CURRENT_SPD_AFTER ((milliseconds_T) 100)
18 int
19 has_progress(struct progress *progress)
21 timeval_T current_speed_after;
23 timeval_from_milliseconds(&current_speed_after, CURRENT_SPD_AFTER);
25 return (timeval_cmp(&progress->elapsed, &current_speed_after) >= 0);
28 struct progress *
29 init_progress(off_t start)
31 struct progress *progress = mem_calloc(1, sizeof(*progress));
33 if (progress) {
34 progress->start = start;
35 progress->timer = TIMER_ID_UNDEF;
38 return progress;
41 void
42 done_progress(struct progress *progress)
44 assert(progress->timer == TIMER_ID_UNDEF);
45 mem_free(progress);
48 /** Timer callback for progress.timer. As explained in install_timer(),
49 * this function must erase the expired timer ID from all variables. */
50 static void
51 progress_timeout(void *progress_voidptr)
53 struct progress *const progress = progress_voidptr;
55 progress->timer = TIMER_ID_UNDEF;
56 /* The expired timer ID has now been erased. */
58 progress->timer_func(progress->timer_func_data);
61 /* Usually called from the timer callback of @progress->timer. */
62 void
63 update_progress(struct progress *progress, off_t loaded, off_t size, off_t pos)
65 off_t bytes_delta;
66 timeval_T now, elapsed, dis_b_max, dis_b_interval;
68 timeval_now(&now);
69 timeval_sub(&elapsed, &progress->last_time, &now);
70 timeval_copy(&progress->last_time, &now);
72 progress->loaded = loaded;
73 bytes_delta = progress->loaded - progress->last_loaded;
74 progress->last_loaded = progress->loaded;
76 timeval_add_interval(&progress->elapsed, &elapsed);
78 timeval_add_interval(&progress->dis_b, &elapsed);
79 timeval_from_milliseconds(&dis_b_max, mult_ms(SPD_DISP_TIME, CURRENT_SPD_SEC));
80 timeval_from_milliseconds(&dis_b_interval, SPD_DISP_TIME);
82 while (timeval_cmp(&progress->dis_b, &dis_b_max) >= 0) {
83 progress->cur_loaded -= progress->data_in_secs[0];
84 memmove(progress->data_in_secs, progress->data_in_secs + 1,
85 sizeof(*progress->data_in_secs) * (CURRENT_SPD_SEC - 1));
86 progress->data_in_secs[CURRENT_SPD_SEC - 1] = 0;
87 timeval_sub_interval(&progress->dis_b, &dis_b_interval);
89 progress->data_in_secs[CURRENT_SPD_SEC - 1] += bytes_delta;
90 progress->cur_loaded += bytes_delta;
92 progress->current_speed = progress->cur_loaded / (CURRENT_SPD_SEC * ((long) SPD_DISP_TIME) / 1000);
94 progress->pos = pos;
95 progress->size = size;
96 if (progress->size != -1 && progress->size < progress->pos)
97 progress->size = progress->pos;
99 progress->average_speed = timeval_div_off_t(progress->loaded, &progress->elapsed);
100 if (progress->average_speed) /* Division by zero risk */
101 timeval_from_seconds(&progress->estimated_time,
102 (progress->size - progress->pos) / progress->average_speed);
104 install_timer(&progress->timer, SPD_DISP_TIME,
105 progress_timeout, progress);
108 /*! Unlike in install_timer(), @a timer_func need not erase the
109 * expired timer ID from @a progress->timer. update_progress()
110 * installs the timer with a wrapper function that takes care of
111 * erasing the timer ID. */
112 void
113 start_update_progress(struct progress *progress, void (*timer_func)(void *),
114 void *timer_func_data)
116 if (!progress->valid) {
117 struct progress tmp;
119 /* Just copy useful fields from invalid progress. */
120 memset(&tmp, 0, sizeof(tmp));
121 tmp.start = progress->start;
122 tmp.seek = progress->seek;
123 tmp.valid = 1;
125 memcpy(progress, &tmp, sizeof(*progress));
127 timeval_now(&progress->last_time);
128 progress->last_loaded = progress->loaded;
129 progress->timer_func = timer_func;
130 progress->timer_func_data = timer_func_data;