dfu: Improve progress display 16/229016/6
authorDongwoo Lee <dwoo08.lee@samsung.com>
Wed, 1 Apr 2020 01:43:52 +0000 (10:43 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Thu, 2 Apr 2020 03:20:17 +0000 (12:20 +0900)
Since commit 951986d4deb9 ("thor: Use smaller flash unit size"), the
number of character '#' is extremely increased while transfer is
proceeded. For removing it and providing fancy progress bar, this
reworks progress display.

Change-Id: Ic21ec3f1c87a469f23f6c892cfd341f956777930
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
src/dfu.c

index 166185c..8a477de 100644 (file)
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -40,6 +40,9 @@
 
 #define DFU_IOQ_MAXLEN         5
 
+#define DFU_PROG_BAR_NAME_WIDTH        20
+#define DFU_PROG_BAR_WIDTH     50
+
 enum dfu_entry_attr {
        DFU_INFO_MODE = 0,
        DFU_INFO_PARTITION,
@@ -264,6 +267,68 @@ static void dfu_thread_cleanup(void *ptr)
        free(e);
 }
 
+static inline void print_bar_label(const char *label)
+{
+       fprintf(stdout, "\n[ %*s |", DFU_PROG_BAR_NAME_WIDTH, label);
+}
+
+static void print_bar(uint64_t progress, uint64_t total, int *prev_rate)
+{
+       int rate = (progress * DFU_PROG_BAR_WIDTH) / total;
+       int bar_margin = DFU_PROG_BAR_NAME_WIDTH + 4;
+       int i;
+
+       if (*prev_rate == rate) {
+               fprintf(stdout, "\x1b[%dC", bar_margin + DFU_PROG_BAR_WIDTH);
+               goto skip_bar;
+       }
+
+       *prev_rate = rate;
+
+       fprintf(stdout, "\x1b[%dC", bar_margin);
+
+       for (i = 0; i < DFU_PROG_BAR_WIDTH; i++) {
+               if (i < rate)
+                       fputc('=', stdout);
+               else if (i == rate)
+                       fputc('>', stdout);
+               else
+                       fputc(' ', stdout);
+       }
+
+skip_bar:
+       fprintf(stdout, "] (%5.1f%%)",
+               (double)progress / (double)total * 100.0F);
+}
+
+static void print_progress(struct dfu_entry *e, uint64_t progress)
+{
+       struct dfu_context *ctx = e->ctx;
+       static int nth_entry = 1;
+       static uint64_t completed;
+       static int prev_total_rate;
+       static int prev_entry_rate;
+       uint64_t total_progress;
+
+       total_progress = completed + progress;
+
+       fprintf(stdout, "\x1b[%dA\n\x1b[1A", nth_entry);
+       print_bar(total_progress, ctx->total_size, &prev_total_rate);
+
+       fprintf(stdout, "\x1b[%dB\n\x1b[1A", nth_entry);
+       print_bar(progress, e->file_size, &prev_entry_rate);
+
+       /* prepare for next entry if current is finished */
+       if (progress == e->file_size) {
+               completed += e->file_size;
+               nth_entry++;
+       }
+
+       if (total_progress == ctx->total_size)
+               fprintf(stdout, "\nDownload Finished\n");
+       fflush(stdout);
+}
+
 static void *dfu_thread_main(void *ptr)
 {
        struct dfu_entry *e = ptr;
@@ -307,8 +372,7 @@ static void *dfu_thread_main(void *ptr)
                ctx->ioq_len--;
                pthread_mutex_unlock(&ctx->mutex);
 
-               fprintf(stdout, "#");
-               fflush(stdout);
+               print_progress(e, progress);
 
                free(frame->buf);
                free(frame);
@@ -401,8 +465,10 @@ void dfu_init_download(struct dfu_context *ctx, uint64_t size)
 {
        ctx->total_size = size;
 
-       fprintf(stdout, "Start Download (Total: %.2lfMB)\n",
+       fprintf(stdout, "Start Download (Total: %.2lfMB)",
                        (double)size / (1024.0f * 1024.0f));
+
+       print_bar_label("Total");
 }
 
 struct dfu_entry *dfu_start(struct dfu_context *ctx,
@@ -430,8 +496,7 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx,
                return NULL;
        }
 
-       fprintf(stdout, "Start download: %s...", filename);
-       fflush(stdout);
+       print_bar_label(filename);
 
        e->ctx = ctx;
        pthread_create(&ctx->thread, NULL, dfu_thread_main, e);
@@ -455,8 +520,6 @@ void dfu_sync(struct dfu_entry *e)
                umount_dev();
 
        pthread_cond_signal(&ctx->sync_done);
-
-       fprintf(stdout, "finished\n");
 }
 
 static int parse_dfu_info(char *buf, char **info)