From 87fb007ebcb18dc299993aa966bd8ac47fd7f5c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Mon, 30 Nov 2015 08:33:54 -0300 Subject: [PATCH 1/4] (runloop_data.c) Get rid of data_runloop_msg rarch_main_msg_queue_push*() functions are thread safe and can be called from anywhere. --- runloop_data.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/runloop_data.c b/runloop_data.c index 3e578bf630..500e7e28b1 100644 --- a/runloop_data.c +++ b/runloop_data.c @@ -20,8 +20,6 @@ #include "tasks/tasks.h" -static char data_runloop_msg[PATH_MAX_LENGTH]; - void rarch_main_data_deinit(void) { rarch_task_deinit(); @@ -29,12 +27,6 @@ void rarch_main_data_deinit(void) void rarch_main_data_iterate(void) { - if (data_runloop_msg[0] != '\0') - { - rarch_main_msg_queue_push(data_runloop_msg, 1, 10, true); - data_runloop_msg[0] = '\0'; - } - rarch_task_check(); } @@ -46,5 +38,5 @@ void rarch_main_data_clear_state(void) void data_runloop_osd_msg(const char *msg, size_t len) { - strlcpy(data_runloop_msg, msg, len); + rarch_main_msg_queue_push(msg, 1, 10, true); } From 7e156584baaf04052e7fd55c3144e3f60e942451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Mon, 30 Nov 2015 09:17:46 -0300 Subject: [PATCH 2/4] (tasks) Add progress metter and task titles --- menu/cbs/menu_cbs_ok.c | 7 ------- tasks/task_http.c | 27 +++++++++------------------ tasks/tasks.c | 35 +++++++++++++++++++++++++++++++++-- tasks/tasks.h | 4 ++++ 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 921298e2cf..f9bbbd2a43 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -1172,13 +1172,6 @@ static int action_ok_download_generic(const char *path, transf->type_hash = menu_hash_calculate(type_msg); strlcpy(transf->path, path, sizeof(transf->path)); - snprintf(s2, sizeof(s2), - "%s %s.", - menu_hash_to_str(MENU_LABEL_VALUE_STARTING_DOWNLOAD), - path); - - menu_display_msg_queue_push(s2, 1, 90, true); - rarch_task_push_http_transfer(s3, type_msg, cb_generic_download, transf); #endif return 0; diff --git a/tasks/task_http.c b/tasks/task_http.c index df70ec6def..2030899d1f 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -110,28 +110,14 @@ static int cb_http_conn_default(void *data_, size_t len) * Returns: 0 when finished, -1 when we should continue * with the transfer on the next frame. **/ -static int rarch_main_data_http_iterate_transfer(void *data) +static int rarch_main_data_http_iterate_transfer(rarch_task_t *task) { - http_handle_t *http = (http_handle_t*)data; + http_handle_t *http = (http_handle_t*)task->state; size_t pos = 0, tot = 0; if (!net_http_update(http->handle, &pos, &tot)) { - int percent = 0; - - if(tot != 0) - percent = (unsigned long long)pos * 100 - / (unsigned long long)tot; - - if (percent > 0) - { - char tmp[PATH_MAX_LENGTH]; - snprintf(tmp, sizeof(tmp), "%s: %d%%", - msg_hash_to_str(MSG_DOWNLOAD_PROGRESS), - percent); - data_runloop_osd_msg(tmp, sizeof(tmp)); - } - + task->progress = tot == 0 ? -1 : (pos * 100 / tot); return -1; } @@ -154,7 +140,7 @@ static void rarch_task_http_transfer_handler(rarch_task_t *task) http->status = HTTP_STATUS_CONNECTION_TRANSFER_PARSE; break; case HTTP_STATUS_TRANSFER: - if (!rarch_main_data_http_iterate_transfer(http)) + if (!rarch_main_data_http_iterate_transfer(task)) goto task_finished; break; case HTTP_STATUS_TRANSFER_PARSE: @@ -212,6 +198,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task rarch_task_t *t; http_handle_t *http; struct http_connection_t *conn; + char tmp[PATH_MAX_LENGTH]; if (!url || !*url) return false; @@ -235,6 +222,10 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task t->state = http; t->callback = cb; t->user_data = user_data; + t->progress = -1; + + snprintf(tmp, sizeof(tmp), "Downloading '%s'", path_basename(url)); + t->title = strdup(tmp); rarch_task_push(t); diff --git a/tasks/tasks.c b/tasks/tasks.c index c5f1197fea..92327ea57b 100644 --- a/tasks/tasks.c +++ b/tasks/tasks.c @@ -63,10 +63,34 @@ static void rarch_task_internal_gather(void) if (task->error) free(task->error); + if (task->title) + free(task->title); + free(task); } } +static void push_task_progress(rarch_task_t *task) +{ + if (task->title) + { + if (task->finished) + { + if (task->error) + rarch_main_msg_queue_pushf(1, 60, true, "Failed: %s", task->title); + else + rarch_main_msg_queue_pushf(1, 60, true, "100%%: %s", task->title); + } + else + { + if (task->progress >= 0 && task->progress <= 100) + rarch_main_msg_queue_pushf(1, 10, true, "%i%%: %s", task->progress, task->title); + else + rarch_main_msg_queue_pushf(1, 10, true, "%s...", task->title); + } + } +} + static void regular_push_running(rarch_task_t *task) { task_queue_put(&tasks_running, task); @@ -78,8 +102,6 @@ static void regular_gather(void) rarch_task_t *queue = NULL; rarch_task_t *next = NULL; - /* mimics threaded_gather() for compatibility, a faster implementation - * can be written for systems without HAVE_THREADS if necessary. */ while ((task = task_queue_get(&tasks_running)) != NULL) { task->next = queue; @@ -91,6 +113,8 @@ static void regular_gather(void) next = task->next; task->handler(task); + push_task_progress(task); + if (task->finished) task_queue_put(&tasks_finished, task); else @@ -148,6 +172,13 @@ static void threaded_push_running(rarch_task_t *task) static void threaded_gather(void) { + rarch_task_t *task; + slock_lock(running_lock); + for (task = tasks_running.front; task; task = task->next) + push_task_progress(task); + + slock_unlock(running_lock); + slock_lock(finished_lock); rarch_task_internal_gather(); slock_unlock(finished_lock); diff --git a/tasks/tasks.h b/tasks/tasks.h index 0c31243c52..92bd0b86c4 100644 --- a/tasks/tasks.h +++ b/tasks/tasks.h @@ -55,6 +55,10 @@ struct rarch_task { /* created by task handler; destroyed by main loop (after calling the callback) */ char *error; + /* -1 = unmettered, 0-100 progress value */ + char progress; + char *title; /* handler can modify but will be free()d automatically if non-null */ + /* don't touch this. */ rarch_task_t *next; }; From cf0a493605c6af38bd291a14aab77346e630ea07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Mon, 30 Nov 2015 10:02:36 -0300 Subject: [PATCH 3/4] Add some task-related localized strings --- intl/msg_hash_es.c | 8 ++++---- intl/msg_hash_pl.c | 4 ---- intl/msg_hash_pt.c | 10 ++++++---- intl/msg_hash_us.c | 10 ++++++---- menu/cbs/menu_cbs_deferred_push.c | 21 ++------------------- msg_hash.h | 6 ++++-- tasks/task_decompress.c | 5 +++++ tasks/task_http.c | 2 +- tasks/tasks.c | 4 +++- 9 files changed, 31 insertions(+), 39 deletions(-) diff --git a/intl/msg_hash_es.c b/intl/msg_hash_es.c index 382916cf28..5041dfbea3 100644 --- a/intl/msg_hash_es.c +++ b/intl/msg_hash_es.c @@ -157,12 +157,8 @@ const char *msg_hash_to_str_es(uint32_t hash) return "Borrando archivo temporal de contenido"; case MSG_LOADED_STATE_FROM_SLOT: return "Carga rápida desde la ranura"; - case MSG_DOWNLOAD_PROGRESS: - return "Progreso de la descarga"; case MSG_COULD_NOT_PROCESS_ZIP_FILE: return "No se ha podido procesar el archivo ZIP."; - case MSG_DOWNLOAD_COMPLETE: - return "Descarga completa"; case MSG_SCANNING_OF_DIRECTORY_FINISHED: return "Escaneado de carpetas terminado"; case MSG_SCANNING: @@ -195,6 +191,10 @@ const char *msg_hash_to_str_es(uint32_t hash) return "Rebobinando."; case MSG_REWIND_REACHED_END: return "Se ha llegado al final del búfer de rebobinado."; + case MSG_TASK_FAILED: + return "Fracasado"; + case MSG_DOWNLOADING: + return "Descargando"; default: break; } diff --git a/intl/msg_hash_pl.c b/intl/msg_hash_pl.c index d5562743a7..0fd325f72b 100644 --- a/intl/msg_hash_pl.c +++ b/intl/msg_hash_pl.c @@ -148,12 +148,8 @@ const char *msg_hash_to_str_pl(uint32_t hash) return "Usuwanie tymczasowego pliku treÅ›ci"; case MSG_LOADED_STATE_FROM_SLOT: return "Wczytano stan ze slotu"; - case MSG_DOWNLOAD_PROGRESS: - return "PostÄ™p pobierania"; case MSG_COULD_NOT_PROCESS_ZIP_FILE: return "Nie udaÅ‚o siÄ™ przetworzyć pliku ZIP."; - case MSG_DOWNLOAD_COMPLETE: - return "ZakoÅ„czono pobieranie"; case MSG_SCANNING_OF_DIRECTORY_FINISHED: return "ZakoÅ„czono skanowanie katalogu"; case MSG_SCANNING: diff --git a/intl/msg_hash_pt.c b/intl/msg_hash_pt.c index 864d738ea7..f40c8d980d 100644 --- a/intl/msg_hash_pt.c +++ b/intl/msg_hash_pt.c @@ -100,12 +100,8 @@ const char *msg_hash_to_str_pt(uint32_t hash) return "Removendo conteúdo temporário"; case MSG_LOADED_STATE_FROM_SLOT: return "Estado carregado do slot"; - case MSG_DOWNLOAD_PROGRESS: - return "Progresso do download"; case MSG_COULD_NOT_PROCESS_ZIP_FILE: return "Incapaz de processar arquivo ZIP."; - case MSG_DOWNLOAD_COMPLETE: - return "Download concluído"; case MSG_SCANNING_OF_DIRECTORY_FINISHED: return "Exame de diretório concluído"; case MSG_SCANNING: @@ -138,6 +134,12 @@ const char *msg_hash_to_str_pt(uint32_t hash) return "Retrocedendo."; case MSG_REWIND_REACHED_END: return "Final do buffer de retrocesso atingido."; + case MSG_TASK_FAILED: + return "Falhou"; + case MSG_DOWNLOADING: + return "Baixando"; + case MSG_EXTRACTING: + return "Extraindo"; default: break; } diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index 7fe45b3391..dcde769495 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -148,12 +148,8 @@ const char *msg_hash_to_str_us(uint32_t hash) return "Removing temporary content file"; case MSG_LOADED_STATE_FROM_SLOT: return "Loaded state from slot"; - case MSG_DOWNLOAD_PROGRESS: - return "Download progress"; case MSG_COULD_NOT_PROCESS_ZIP_FILE: return "Could not process ZIP file."; - case MSG_DOWNLOAD_COMPLETE: - return "Download complete"; case MSG_SCANNING_OF_DIRECTORY_FINISHED: return "Scanning of directory finished"; case MSG_SCANNING: @@ -186,6 +182,12 @@ const char *msg_hash_to_str_us(uint32_t hash) return "Rewinding."; case MSG_REWIND_REACHED_END: return "Reached end of rewind buffer."; + case MSG_TASK_FAILED: + return "Failed"; + case MSG_DOWNLOADING: + return "Downloading"; + case MSG_EXTRACTING: + return "Extracting"; default: break; } diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index ce9858e3f6..35094495d9 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -338,15 +338,10 @@ static void cb_decompressed(void *task_data, void *user_data, const char *err) if (dec && !err) { - char msg[PATH_MAX_LENGTH]; - if (type_hash == CB_CORE_UPDATER_DOWNLOAD) event_command(EVENT_CMD_CORE_INFO_INIT); else if (type_hash == CB_UPDATE_ASSETS) event_command(EVENT_CMD_REINIT); - - snprintf(msg, sizeof(msg), "%s extracted.", path_basename(dec->source_file)); - rarch_main_msg_queue_push(msg, 1, 90, true); } if (err) @@ -448,9 +443,6 @@ void cb_generic_download(void *task_data, void *user_data, const char *err) goto finish; } - rarch_main_msg_queue_pushf(1, 90, true, "%s: %s", - msg_hash_to_str(MSG_DOWNLOAD_COMPLETE), transf->path); - #ifdef HAVE_ZLIB file_ext = path_get_extension(output_path); @@ -459,15 +451,8 @@ void cb_generic_download(void *task_data, void *user_data, const char *err) if (!strcasecmp(file_ext, "zip")) { - rarch_main_msg_queue_pushf(1, 90, true, - "Decompressing %s...", path_basename(output_path)); - - if (!rarch_task_push_decompress(output_path, dir_path, NULL, - cb_decompressed, (void*)(uintptr_t)transf->type_hash)) - { - rarch_main_msg_queue_pushf(1, 90, true, - "Decompression of %s failed.", path_basename(output_path)); - } + rarch_task_push_decompress(output_path, dir_path, NULL, + cb_decompressed, (void*)(uintptr_t)transf->type_hash); } #else if (transf->type_hash == CB_CORE_UPDATER_DOWNLOAD) @@ -477,8 +462,6 @@ void cb_generic_download(void *task_data, void *user_data, const char *err) finish: if (err) { - rarch_main_msg_queue_pushf(1, 90, true, "Download failed."); - RARCH_ERR("Download of '%s' failed: %s\n", (transf ? transf->path: "unknown"), err); } diff --git a/msg_hash.h b/msg_hash.h index 5b866d06ba..9aa265ae9b 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -101,9 +101,7 @@ #define MSG_SCANNING 0x4c547516U #define MSG_SCANNING_OF_DIRECTORY_FINISHED 0x399632a7U -#define MSG_DOWNLOAD_COMPLETE 0x4b9c4f75U #define MSG_COULD_NOT_PROCESS_ZIP_FILE 0xc18c89bbU -#define MSG_DOWNLOAD_PROGRESS 0x35ed9411U #define MSG_LOADED_STATE_FROM_SLOT 0xadb48582U @@ -153,6 +151,10 @@ #define MSG_GOT_INVALID_DISK_INDEX 0xb138dd76U +#define MSG_TASK_FAILED 0xb23ed64aU +#define MSG_DOWNLOADING 0x465305dbU +#define MSG_EXTRACTING 0x25a4c19eU + const char *msg_hash_to_str(uint32_t hash); const char *msg_hash_to_str_fr(uint32_t hash); diff --git a/tasks/task_decompress.c b/tasks/task_decompress.c index e48d86d1cc..ccef64fa87 100644 --- a/tasks/task_decompress.c +++ b/tasks/task_decompress.c @@ -23,6 +23,7 @@ #include "tasks.h" #include "../verbosity.h" +#include "../msg_hash.h" typedef struct { char *source_file; @@ -115,6 +116,7 @@ bool rarch_task_push_decompress(const char *source_file, const char *target_dir, { decompress_state_t *s; rarch_task_t *t; + char tmp[PATH_MAX_LENGTH]; if (!target_dir || !target_dir[0] || !source_file || !source_file[0]) { @@ -148,6 +150,9 @@ bool rarch_task_push_decompress(const char *source_file, const char *target_dir, t->callback = cb; t->user_data = user_data; + snprintf(tmp, sizeof(tmp), "%s '%s'", msg_hash_to_str(MSG_EXTRACTING), path_basename(source_file)); + t->title = strdup(tmp); + rarch_task_push(t); return true; diff --git a/tasks/task_http.c b/tasks/task_http.c index 2030899d1f..702dc6a080 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -224,7 +224,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task t->user_data = user_data; t->progress = -1; - snprintf(tmp, sizeof(tmp), "Downloading '%s'", path_basename(url)); + snprintf(tmp, sizeof(tmp), "%s '%s'", msg_hash_to_str(MSG_DOWNLOADING), path_basename(url)); t->title = strdup(tmp); rarch_task_push(t); diff --git a/tasks/tasks.c b/tasks/tasks.c index 92327ea57b..ae347e69dd 100644 --- a/tasks/tasks.c +++ b/tasks/tasks.c @@ -3,6 +3,7 @@ #include "../general.h" #include "../verbosity.h" +#include "../msg_hash.h" #include "tasks.h" #ifdef HAVE_THREADS @@ -77,7 +78,8 @@ static void push_task_progress(rarch_task_t *task) if (task->finished) { if (task->error) - rarch_main_msg_queue_pushf(1, 60, true, "Failed: %s", task->title); + rarch_main_msg_queue_pushf(1, 60, true, "%s: %s", + msg_hash_to_str(MSG_TASK_FAILED), task->title); else rarch_main_msg_queue_pushf(1, 60, true, "100%%: %s", task->title); } From a171f3c6d14badefd6f759e46ebfca1a631f9a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Mon, 30 Nov 2015 10:41:35 -0300 Subject: [PATCH 4/4] (task_decompress.c) Add progress report --- libretro-common/file/file_extract.c | 9 +++++++++ libretro-common/include/file/file_extract.h | 2 ++ tasks/task_decompress.c | 2 ++ 3 files changed, 13 insertions(+) diff --git a/libretro-common/file/file_extract.c b/libretro-common/file/file_extract.c index b2b789b724..80df90ce89 100644 --- a/libretro-common/file/file_extract.c +++ b/libretro-common/file/file_extract.c @@ -604,6 +604,15 @@ bool zlib_parse_file(const char *file, const char *valid_exts, return returnerr; } +int zlib_parse_file_progress(void *data) +{ + /* FIXME: this estimate is pretty bad */ + zlib_transfer_t *state = (zlib_transfer_t*)data; + const uint8_t *offset = state->data + read_le(state->directory + 42, 4); + ptrdiff_t delta = offset - state->data - 46 - 22; + return delta * 100 / state->zip_size; +} + struct zip_extract_userdata { char *zip_path; diff --git a/libretro-common/include/file/file_extract.h b/libretro-common/include/file/file_extract.h index 6afac0ef7b..6c1ae44f6d 100644 --- a/libretro-common/include/file/file_extract.h +++ b/libretro-common/include/file/file_extract.h @@ -86,6 +86,8 @@ int zlib_parse_file_iterate(void *data, bool *returnerr, void zlib_parse_file_iterate_stop(void *data); +int zlib_parse_file_progress(void *data); + /** * zlib_extract_first_content_file: * @zip_path : filename path to ZIP archive. diff --git a/tasks/task_decompress.c b/tasks/task_decompress.c index ccef64fa87..09aecb8bc5 100644 --- a/tasks/task_decompress.c +++ b/tasks/task_decompress.c @@ -81,6 +81,8 @@ static void rarch_task_decompress_handler(rarch_task_t *task) ret = zlib_parse_file_iterate(&dec->zlib, &returnerr, dec->source_file, dec->valid_ext, file_decompressed, dec); + task->progress = zlib_parse_file_progress(&dec->zlib); + if (task->cancelled || ret != 0) { task->error = dec->callback_error;