pbar: Make progress animation advance from left-to-right
[quvi-tool.git] / src / pbar / lpbar.c
blob5ad099728df644ab3cddc7db198a6253bd9603fb
1 /* quvi
2 * Copyright (C) 2012,2013 Toni Gundogdu <legatvs@gmail.com>
4 * This file is part of quvi <http://quvi.sourceforge.net/>.
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU Affero General Public
8 * License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General
17 * Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
21 #include "config.h"
23 #include <glib/gi18n.h>
25 /* -- */
26 #include "lpbar.h"
28 typedef enum
30 Ki = 1024,
31 Mi = 1048576,
32 Gi = 1073741824,
33 } ieee_1541;
35 #define _s(n) #n
36 static const gchar *_units[] =
38 _s(Ki),
39 _s(Mi),
40 _s(Gi),
41 NULL
43 #undef _s
45 static const gchar *_to_unit(gdouble *n)
47 gint i = 0;
48 if (*n >=Gi)
50 *n /= Gi;
51 i = 2;
53 else if (*n >=Mi)
55 *n /= Mi;
56 i = 1;
58 else
59 *n /= Ki;
60 return (_units[i]);
63 lpbar_t lpbar_new()
65 lpbar_t p = g_new0(struct lpbar_s, 1);
66 p->counters.timer = g_timer_new();
67 return (p);
70 void lpbar_free(lpbar_t p)
72 if (p == NULL)
73 return;
75 if (p->content_bytes >0
76 && (p->counters.count + p->initial_bytes >p->content_bytes))
78 p->content_bytes = p->initial_bytes + p->counters.count;
81 if (p->flags.failed == FALSE)
83 p->flags.done = TRUE;
84 lpbar_update(p, -1);
87 g_timer_destroy(p->counters.timer);
88 g_free(p->content_type);
89 g_free(p->fname);
90 g_free(p);
92 memset(p, 0, sizeof(struct lpbar_s));
95 static const gchar *frames[] =
97 "=---",
98 "-=--",
99 "--=-",
100 "---=",
101 NULL
104 static const gchar *_next_frame(lpbar_t p)
106 if (frames[p->counters.curr_frame] == NULL)
107 p->counters.curr_frame = 0;
108 return (frames[p->counters.curr_frame++]);
111 static gchar *_eta(const glong s)
113 if (s >=86400) /* 24h */
114 return (g_strdup_printf(_("%ld hours"), (s/3600%60)));
115 return (g_strdup_printf("%02ld:%02ld:%02ld", (s/3600)%60, (s/60)%60, s%60));
118 static const gdouble update_interval = .5;
120 gint lpbar_update(lpbar_t p, gdouble dlnow)
122 gdouble rate, size, elapsed, percent;
123 const gchar *rate_unit, *frame;
124 gboolean inactive;
125 gchar *eta;
127 if (dlnow == 0 || p->flags.failed == TRUE)
128 return (0);
130 elapsed = g_timer_elapsed(p->counters.timer, NULL);
132 if (p->flags.done == TRUE)
133 dlnow = p->content_bytes;
134 else
136 if ((elapsed - p->counters.last_update) < update_interval)
137 return (0);
140 size = dlnow;
141 if (p->flags.done == FALSE)
142 size += p->initial_bytes;
144 inactive = (dlnow == 0) ? TRUE:FALSE;
145 rate = (elapsed >0) ? (dlnow/elapsed):0;
147 if (inactive == FALSE)
149 if (p->flags.done == FALSE)
151 const gdouble left =
152 (p->content_bytes - (dlnow + p->initial_bytes)) / rate;
154 eta = _eta(left+.5);
156 else
158 rate = (p->content_bytes - p->initial_bytes) / elapsed;
159 eta = _eta(elapsed);
161 rate_unit = _to_unit(&rate);
162 frame = _next_frame(p);
164 else
166 frame = frames[p->counters.curr_frame];
167 eta = g_strdup("--:--");
168 rate_unit = "--.-";
171 percent = 0;
172 if (p->content_bytes >0)
174 percent = (100.0 * size / p->content_bytes);
175 if (percent >= 100)
176 percent = 100;
179 g_print("\r");
180 g_print(_("copy: %s %3.0f%% %6.1f%s/s %4s%s"),
181 frame, percent, rate, rate_unit, eta,
182 (p->flags.done == TRUE) ? "\n":"");
184 p->counters.last_update = elapsed;
185 p->counters.count = dlnow;
186 g_free(eta);
188 return (0);
191 void lpbar_print(const lpbar_t p, const gboolean skip_transfer)
193 const gchar *u;
194 gdouble b;
196 b = p->content_bytes;
197 u = _to_unit(&b);
199 g_print(_("file: %s [media]\n"), p->fname);
200 g_print(_(" content length: %.1f%s"), b, u);
202 if (p->content_type != NULL)
203 g_print(_(" content type: %s"), p->content_type);
205 if (skip_transfer == FALSE)
207 g_print(_(" mode: %s"),
208 (p->initial_bytes >0) ? _("resume"):_("write"));
210 g_print("\n");
213 /* vim: set ts=2 sw=2 tw=72 expandtab: */