From e9cd81683996802f2ed95fce5a1a8dedb6f2f5e5 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 7 Apr 2015 16:48:49 +0900 Subject: [PATCH] ecore_evas_convert: Implement hacky solution for Ctrl+C Problem: evas_object_image_save() can't be interrupted. But, with ETC1/ETC2 encoding, it might be terribly long and the user has no way to cancel encoding (except SIGKILL). The proper solution would be to tell evas that the save operation has been cancelled. And run that in a thread, in a non-blocking way. I guess Efl.File.async could be used for that, which means maybe also introduce Efl.File.async_cancel? This will have to wait for EFL 1.15 I'm afraid. Note: edje_cc still can't be cancelled during ETC encoding. --- src/bin/ecore_evas/ecore_evas_convert.c | 65 ++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/src/bin/ecore_evas/ecore_evas_convert.c b/src/bin/ecore_evas/ecore_evas_convert.c index 8cf613e211..d23d3579ed 100644 --- a/src/bin/ecore_evas/ecore_evas_convert.c +++ b/src/bin/ecore_evas/ecore_evas_convert.c @@ -36,6 +36,54 @@ const Ecore_Getopt optdesc = { } }; +struct Save_Job { + const char *output; + const char *flags; + Ecore_Thread *th; + Evas_Object *im; + int ret, cancel; +}; + +static void +_save_do(void *data, Ecore_Thread *thread EINA_UNUSED) +{ + struct Save_Job *job = data; + + job->ret = 0; + if (!evas_object_image_save(job->im, job->output, NULL, job->flags)) + { + EINA_LOG_ERR("Could not convert file to '%s'.", job->output); + job->ret = 1; + } +} + +static void +_save_end(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static Eina_Bool +exit_func(void *data, int ev_type EINA_UNUSED, void *ev) +{ + Ecore_Event_Signal_Exit *e = ev; + struct Save_Job *job = data; + if (!job->cancel && !e->quit && !e->terminate) + { + // this won't do anything, really... + fprintf(stderr, "Cancellation requested. Press Ctrl+C again to kill.\n"); + fflush(stderr); + job->cancel = 1; + ecore_thread_cancel(job->th); + } + else + { + fprintf(stderr, "Terminated."); + exit(1); + } + return ECORE_CALLBACK_RENEW; +} + int main(int argc, char *argv[]) { @@ -49,6 +97,7 @@ main(int argc, char *argv[]) Eina_Bool compress = 1; Eina_Bool quit_option = EINA_FALSE; Eina_Strbuf *flags = NULL; + struct Save_Job job = {0}; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_INT(quality), @@ -107,14 +156,16 @@ main(int argc, char *argv[]) goto end; } - if (!evas_object_image_save(im, argv[arg_index + 1], NULL, - eina_strbuf_string_get(flags))) - { - EINA_LOG_ERR("Could not convert file to '%s'.", argv[arg_index + 1]); - goto end; - } + // NOTE: DO NOT DO THIS AT HOME -- HACK for Ctrl+C + // This makes Ctrl+C work but the Evas Object may not be deleted cleanly + job.output = argv[arg_index + 1]; + job.flags = eina_strbuf_string_get(flags); + job.im = im; + job.th = ecore_thread_run(_save_do, _save_end, _save_end, &job); + ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, exit_func, &job); + ecore_main_loop_begin(); - r = 0; + r = job.ret; end: if (flags) eina_strbuf_free(flags);