1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2023 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (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 General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
25 #include <pakfire/pakfire.h>
26 #include <pakfire/private.h>
27 #include <pakfire/progress.h>
29 struct pakfire_progress
{
30 struct pakfire
* pakfire
;
40 enum pakfire_progress_status
{
41 PAKFIRE_PROGRESS_INIT
= 0,
42 PAKFIRE_PROGRESS_RUNNING
,
43 PAKFIRE_PROGRESS_FINISHED
,
47 struct pakfire_progress_callbacks
{
50 pakfire_progress_start_callback start
;
51 pakfire_progress_finish_callback finish
;
52 pakfire_progress_update_callback update
;
53 pakfire_progress_free_callback free
;
57 struct timespec time_start
;
58 struct timespec time_finished
;
61 unsigned long int value
;
62 unsigned long int max_value
;
65 static void pakfire_progress_free(struct pakfire_progress
* p
) {
66 // Ensure this is finished
67 pakfire_progress_finish(p
);
69 // Call the free callback
70 if (p
->callbacks
.free
)
71 p
->callbacks
.free(p
->pakfire
, p
, p
->callbacks
.data
);
75 pakfire_unref(p
->pakfire
);
79 int pakfire_progress_create(struct pakfire_progress
** progress
,
80 struct pakfire
* pakfire
, int flags
) {
81 struct pakfire_progress
* p
= NULL
;
84 // Allocate a new object
85 p
= calloc(1, sizeof(*p
));
89 // Store a reference to Pakfire
90 p
->pakfire
= pakfire_ref(pakfire
);
92 // Initialize the reference counter
99 p
->status
= PAKFIRE_PROGRESS_INIT
;
101 // XXX Create a couple of default callbacks
104 if (!pakfire_progress_has_flag(p
, PAKFIRE_PROGRESS_NO_PROGRESS
)) {
105 r
= pakfire_setup_progress(pakfire
, p
);
116 pakfire_progress_unref(p
);
121 struct pakfire_progress
* pakfire_progress_ref(struct pakfire_progress
* p
) {
127 struct pakfire_progress
* pakfire_progress_unref(struct pakfire_progress
* p
) {
131 pakfire_progress_free(p
);
135 PAKFIRE_EXPORT
int pakfire_progress_has_flag(struct pakfire_progress
* p
, int flag
) {
136 return p
->flags
& flag
;
140 Callback Configuration
143 PAKFIRE_EXPORT
void pakfire_progress_set_callback_data(struct pakfire_progress
* p
, void* data
) {
144 p
->callbacks
.data
= data
;
147 PAKFIRE_EXPORT
void pakfire_progress_set_start_callback(
148 struct pakfire_progress
* p
, pakfire_progress_start_callback callback
) {
149 p
->callbacks
.start
= callback
;
152 PAKFIRE_EXPORT
void pakfire_progress_set_finish_callback(
153 struct pakfire_progress
* p
, pakfire_progress_finish_callback callback
) {
154 p
->callbacks
.finish
= callback
;
157 PAKFIRE_EXPORT
void pakfire_progress_set_update_callback(
158 struct pakfire_progress
* p
, pakfire_progress_update_callback callback
) {
159 p
->callbacks
.update
= callback
;
162 PAKFIRE_EXPORT
void pakfire_progress_set_free_callback(
163 struct pakfire_progress
* p
, pakfire_progress_free_callback callback
) {
164 p
->callbacks
.free
= callback
;
167 int pakfire_progress_start(struct pakfire_progress
* p
, unsigned long int value
) {
170 // This can only be called once
171 if (p
->status
== PAKFIRE_PROGRESS_RUNNING
)
174 // We are now running...
175 p
->status
= PAKFIRE_PROGRESS_RUNNING
;
177 // Store the max value
178 p
->max_value
= value
;
181 r
= clock_gettime(CLOCK_REALTIME
, &p
->time_start
);
186 if (pakfire_progress_has_flag(p
, PAKFIRE_PROGRESS_NO_PROGRESS
))
189 // Call the start callback
190 if (p
->callbacks
.start
) {
191 r
= p
->callbacks
.start(p
->pakfire
, p
, p
->callbacks
.data
, value
);
196 // Call the first update
197 return pakfire_progress_update(p
, 0);
200 int pakfire_progress_finish(struct pakfire_progress
* p
) {
203 // Do nothing if already finished
204 if (p
->status
== PAKFIRE_PROGRESS_FINISHED
)
208 if (pakfire_progress_has_flag(p
, PAKFIRE_PROGRESS_NO_PROGRESS
))
212 r
= clock_gettime(CLOCK_REALTIME
, &p
->time_finished
);
216 // Call the finish callback
217 if (p
->callbacks
.finish
) {
218 r
= p
->callbacks
.finish(p
->pakfire
, p
, p
->callbacks
.data
);
226 int pakfire_progress_update(struct pakfire_progress
* p
, unsigned long int value
) {
229 // Store the new value
233 if (pakfire_progress_has_flag(p
, PAKFIRE_PROGRESS_NO_PROGRESS
))
236 // Call the update callback
237 if (p
->callbacks
.update
) {
238 r
= p
->callbacks
.update(p
->pakfire
, p
, p
->callbacks
.data
, value
);
246 PAKFIRE_EXPORT
unsigned long int pakfire_progress_get_value(struct pakfire_progress
* p
) {
250 PAKFIRE_EXPORT
unsigned long int pakfire_progress_get_max_value(struct pakfire_progress
* p
) {
254 PAKFIRE_EXPORT
const char* pakfire_progress_get_title(struct pakfire_progress
* p
) {
258 int pakfire_progress_set_title(struct pakfire_progress
* p
, const char* format
, ...) {
263 va_start(args
, format
);
264 r
= vasprintf(&p
->title
, format
, args
);
274 PAKFIRE_EXPORT
double pakfire_progress_get_percentage(struct pakfire_progress
* p
) {
278 return p
->value
* 100.0 / p
->max_value
;
281 PAKFIRE_EXPORT
time_t pakfire_progress_get_elapsed_time(struct pakfire_progress
* p
) {
286 case PAKFIRE_PROGRESS_INIT
:
289 case PAKFIRE_PROGRESS_RUNNING
:
290 r
= clock_gettime(CLOCK_REALTIME
, &now
);
294 return now
.tv_sec
- p
->time_start
.tv_sec
;
296 case PAKFIRE_PROGRESS_FINISHED
:
297 return p
->time_finished
.tv_sec
- p
->time_start
.tv_sec
;
303 PAKFIRE_EXPORT
time_t pakfire_progress_get_eta(struct pakfire_progress
* p
) {
304 const time_t t
= pakfire_progress_get_elapsed_time(p
);
308 return t
* p
->max_value
/ p
->value
- t
;
311 PAKFIRE_EXPORT
double pakfire_progress_get_transfer_speed(struct pakfire_progress
* p
) {
312 const time_t t
= pakfire_progress_get_elapsed_time(p
);