2013/8/11 Daniel Juyung Seo <[email protected]> > Great! Awesome feature!! > Thanks Cedric. >
indeed awesome feature, I had to implement exactly the same in my mediacenter. > > Daniel Juyung Seo (SeoZ) > > > On Fri, Aug 9, 2013 at 9:14 PM, Cedric Bail - Enlightenment Git < > [email protected]> wrote: > > > cedric pushed a commit to branch master. > > > > commit 05c78b716b7bbec56dc39dc03eaaa26d18efbf9d > > Author: Cedric Bail <[email protected]> > > Date: Fri Aug 9 21:12:29 2013 +0900 > > > > elm_image: add support for url. > > --- > > ChangeLog | 4 ++ > > NEWS | 1 + > > src/bin/test.c | 2 + > > src/bin/test_image.c | 50 +++++++++++++++ > > src/lib/Makefile.am | 1 + > > src/lib/elm_image.c | 141 > > ++++++++++++++++++++++++++++++++++++++++--- > > src/lib/elm_image_common.h | 23 +++++++ > > src/lib/elm_priv.h | 12 ++++ > > src/lib/elm_url.c | 147 > > +++++++++++++++++++++++++++++++++++++++++++++ > > src/lib/elm_widget_image.h | 4 ++ > > 10 files changed, 375 insertions(+), 10 deletions(-) > > > > diff --git a/ChangeLog b/ChangeLog > > index 052bd6c..00d6f9a 100644 > > --- a/ChangeLog > > +++ b/ChangeLog > > @@ -1533,3 +1533,7 @@ > > > > * Fix elm to use key not keyname (otherwise xmodmap and friends > > don't work). > > + > > +2013-08-09 Cedric Bail > > + > > + * Add support for URL in Elm_Image. > > diff --git a/NEWS b/NEWS > > index ab0d982..d639c3c 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -124,6 +124,7 @@ Improvements: > > * Move cursor when mouse moves with longpress. > > * Show magnifier when selection handlers are pressed or moved. > > * Change the method to calculate a distance which be scrolled from > > linear to sine curve. > > + * Add support for URL in Elm_Image. > > > > Fixes: > > * Now elm_datetime_field_limit_set() can set year limits wihtout > > problems. > > diff --git a/src/bin/test.c b/src/bin/test.c > > index 0e2c712..8e0fddf 100644 > > --- a/src/bin/test.c > > +++ b/src/bin/test.c > > @@ -204,6 +204,7 @@ void test_datetime(void *data, Evas_Object *obj, void > > *event_info); > > void test_popup(void *data, Evas_Object *obj, void *event_info); > > void test_dayselector(void *data, Evas_Object *obj, void *event_info); > > void test_image(void *data, Evas_Object *obj, void *event_info); > > +void test_remote_image(void *data, Evas_Object *obj, void *event_info); > > void test_external_button(void *data, Evas_Object *obj, void > *event_info); > > void test_external_slider(void *data, Evas_Object *obj, void > *event_info); > > void test_external_scroller(void *data, Evas_Object *obj, void > > *event_info); > > @@ -528,6 +529,7 @@ add_tests: > > ADD_TEST(NULL, "Images", "Photo", test_photo); > > ADD_TEST(NULL, "Images", "Thumb", test_thumb); > > ADD_TEST(NULL, "Images", "Image", test_image); > > + ADD_TEST(NULL, "Images", "Image Remote", test_remote_image); > > ADD_TEST(NULL, "Images", "Slideshow", test_slideshow); > > #ifdef HAVE_EMOTION > > ADD_TEST(NULL, "Images", "Video", test_video); > > diff --git a/src/bin/test_image.c b/src/bin/test_image.c > > index 4809a64..253dda1 100644 > > --- a/src/bin/test_image.c > > +++ b/src/bin/test_image.c > > @@ -83,4 +83,54 @@ test_image(void *data __UNUSED__, Evas_Object *obj > > __UNUSED__, void *event_info > > evas_object_resize(win, 320, 480); > > evas_object_show(win); > > } > > + > > +void > > +test_remote_image(void *data __UNUSED__, Evas_Object *obj __UNUSED__, > > void *event_info __UNUSED__) > > +{ > > + Evas_Object *win, *box, *im, *rd, *rdg = NULL; > > + int i; > > + > > + win = elm_win_util_standard_add("image test", "Image Test"); > > + elm_win_autodel_set(win, EINA_TRUE); > > + > > + box = elm_box_add(win); > > + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, > > EVAS_HINT_EXPAND); > > + elm_win_resize_object_add(win, box); > > + evas_object_show(box); > > + > > + im = elm_image_add(win); > > + elm_image_file_set(im, " > > > http://31.media.tumblr.com/29f1ecd4f98aaff73fb21f479b450d4c/tumblr_mqsxdciQmB1rrju89o1_1280.jpg > ", > > NULL); > > + elm_image_resizable_set(im, EINA_TRUE, EINA_TRUE); > > + evas_object_size_hint_weight_set(im, EVAS_HINT_EXPAND, > > EVAS_HINT_EXPAND); > > + evas_object_size_hint_align_set(im, EVAS_HINT_FILL, EVAS_HINT_FILL); > > + > > + elm_box_pack_end(box, im); > > + evas_object_show(im); > > + > > + evas_object_data_set(win, "im", im); > > + > > + for (i = 0; images_orient[i].name; ++i) > > + { > > + rd = elm_radio_add(win); > > + evas_object_size_hint_align_set(rd, EVAS_HINT_FILL, > > EVAS_HINT_FILL); > > + evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, 0.0); > > + elm_radio_state_value_set(rd, images_orient[i].orient); > > + elm_object_text_set(rd, images_orient[i].name); > > + elm_box_pack_end(box, rd); > > + evas_object_show(rd); > > + evas_object_smart_callback_add(rd, "changed", my_im_ch, win); > > + if (!rdg) > > + { > > + rdg = rd; > > + evas_object_data_set(win, "rdg", rdg); > > + } > > + else > > + { > > + elm_radio_group_add(rd, rdg); > > + } > > + } > > + > > + evas_object_resize(win, 320, 480); > > + evas_object_show(win); > > +} > > #endif > > diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am > > index 559a459..e87794b 100644 > > --- a/src/lib/Makefile.am > > +++ b/src/lib/Makefile.am > > @@ -463,6 +463,7 @@ elm_thumb.c \ > > elm_toolbar.c \ > > elm_transit.c \ > > elm_util.c \ > > +elm_url.c \ > > elm_video.c \ > > elm_web.c \ > > elm_web2.c \ > > diff --git a/src/lib/elm_image.c b/src/lib/elm_image.c > > index da0ca25..5e3a0c7 100644 > > --- a/src/lib/elm_image.c > > +++ b/src/lib/elm_image.c > > @@ -16,9 +16,17 @@ EAPI Eo_Op ELM_OBJ_IMAGE_BASE_ID = EO_NOOP; > > > > static const char SIG_DND[] = "drop"; > > static const char SIG_CLICKED[] = "clicked"; > > +static const char SIG_DOWNLOAD_START[] = "download,start"; > > +static const char SIG_DOWNLOAD_PROGRESS[] = "download,progress"; > > +static const char SIG_DOWNLOAD_DONE[] = "download,done"; > > +static const char SIG_DOWNLOAD_ERROR[] = "download,error"; > > static const Evas_Smart_Cb_Description _smart_callbacks[] = { > > {SIG_DND, ""}, > > {SIG_CLICKED, ""}, > > + {SIG_DOWNLOAD_START, ""}, > > + {SIG_DOWNLOAD_PROGRESS, ""}, > > + {SIG_DOWNLOAD_DONE, ""}, > > + {SIG_DOWNLOAD_ERROR, ""}, > > {NULL, NULL} > > }; > > > > @@ -183,6 +191,7 @@ _elm_image_internal_sizing_eval(Evas_Object *obj, > > Elm_Image_Smart_Data *sd) > > static Eina_Bool > > _elm_image_edje_file_set(Evas_Object *obj, > > const char *file, > > + Eina_File *f, > > const char *group) > > { > > Evas_Object *pclip; > > @@ -207,7 +216,16 @@ _elm_image_edje_file_set(Evas_Object *obj, > > } > > > > sd->edje = EINA_TRUE; > > - if (!edje_object_file_set(sd->img, file, group)) > > + if (f) > > + { > > + if (!edje_object_mmap_set(sd->img, f, group)) > > + { > > + ERR("failed to set edje file '%s', group '%s': %s", file, > > group, > > + > > edje_load_error_str(edje_object_load_error_get(sd->img))); > > + return EINA_FALSE; > > + } > > + } > > + else if (!edje_object_file_set(sd->img, file, group)) > > { > > ERR("failed to set edje file '%s', group '%s': %s", file, group, > > edje_load_error_str(edje_object_load_error_get(sd->img))); > > @@ -480,6 +498,9 @@ _elm_image_smart_del(Eo *obj, void *_pd, va_list > *list > > EINA_UNUSED) > > if (sd->anim_timer) ecore_timer_del(sd->anim_timer); > > if (sd->img) evas_object_del(sd->img); > > if (sd->prev_img) evas_object_del(sd->prev_img); > > + if (sd->remote) elm_url_cancel(sd->remote); > > + free(sd->remote_data); > > + eina_stringshare_del(sd->key); > > > > eo_do_super(obj, MY_CLASS, evas_obj_smart_del()); > > } > > @@ -810,26 +831,24 @@ elm_image_file_set(Evas_Object *obj, > > } > > > > static void > > -_elm_image_smart_file_set(Eo *obj, void *_pd, va_list *list) > > +_elm_image_smart_internal_file_set(Eo *obj, Elm_Image_Smart_Data *sd, > > + const char *file, Eina_File *f, const > > char *key, Eina_Bool *ret) > > { > > - const char *file = va_arg(*list, const char *); > > - const char *key = va_arg(*list, const char *); > > - Eina_Bool *ret = va_arg(*list, Eina_Bool *); > > - > > Evas_Coord w, h; > > > > - Elm_Image_Smart_Data *sd = _pd; > > - > > if (eina_str_has_extension(file, ".edj")) > > { > > - Eina_Bool int_ret = _elm_image_edje_file_set(obj, file, key); > > + Eina_Bool int_ret = _elm_image_edje_file_set(obj, file, f, key); > > if (ret) *ret = int_ret; > > return; > > } > > > > _elm_image_file_set_do(obj); > > > > - evas_object_image_file_set(sd->img, file, key); > > + if (f) > > + evas_object_image_mmap_set(sd->img, f, key); > > + else > > + evas_object_image_file_set(sd->img, file, key); > > > > sd->preloading = EINA_TRUE; > > evas_object_hide(sd->img); > > @@ -849,6 +868,108 @@ _elm_image_smart_file_set(Eo *obj, void *_pd, > > va_list *list) > > _elm_image_internal_sizing_eval(obj, sd); > > > > if (ret) *ret = EINA_TRUE; > > +} > > + > > +static void > > +_elm_image_smart_download_done(void *data, Elm_Url *url EINA_UNUSED, > > Eina_Binbuf *download) > > +{ > > + Eo *obj = data; > > + Elm_Image_Smart_Data *sd = eo_data_scope_get(obj, MY_CLASS); > > + Eina_File *f; > > + size_t length; > > + Eina_Bool ret = EINA_FALSE; > > + > > + if (sd->remote_data) free(sd->remote_data); > > + length = eina_binbuf_length_get(download); > > + sd->remote_data = eina_binbuf_string_steal(download); > > + f = eina_file_virtualize(elm_url_get(url), > > + sd->remote_data, length, > > + EINA_FALSE); > > + _elm_image_smart_internal_file_set(obj, sd, elm_url_get(url), f, > > sd->key, &ret); > > + eina_file_close(f); > > + > > + if (!ret) > > + { > > + Elm_Image_Error err = { 0, EINA_TRUE }; > > + > > + free(sd->remote_data); > > + sd->remote_data = NULL; > > + evas_object_smart_callback_call(obj, SIG_DOWNLOAD_ERROR, &err); > > + } > > + else > > + { > > + evas_object_smart_callback_call(obj, SIG_DOWNLOAD_DONE, NULL); > > + } > > + > > + sd->remote = NULL; > > + eina_stringshare_del(sd->key); > > + sd->key = NULL; > > +} > > + > > +static void > > +_elm_image_smart_download_cancel(void *data, Elm_Url *url EINA_UNUSED, > > int error) > > +{ > > + Eo *obj = data; > > + Elm_Image_Smart_Data *sd = eo_data_scope_get(obj, MY_CLASS); > > + Elm_Image_Error err = { error, EINA_FALSE }; > > + > > + evas_object_smart_callback_call(obj, SIG_DOWNLOAD_ERROR, &err); > > + > > + sd->remote = NULL; > > + eina_stringshare_del(sd->key); > > + sd->key = NULL; > > +} > > + > > +static void > > +_elm_image_smart_download_progress(void *data, Elm_Url *url EINA_UNUSED, > > double now, double total) > > +{ > > + Eo *obj = data; > > + Elm_Image_Progress progress; > > + > > + progress.now = now; > > + progress.total = total; > > + evas_object_smart_callback_call(obj, SIG_DOWNLOAD_PROGRESS, > &progress); > > +} > > + > > +static const char *remote_uri[] = { > > + "http://", "https://", "ftp://" > > +}; > > + > > +static void > > +_elm_image_smart_file_set(Eo *obj, void *_pd, va_list *list) > > +{ > > + const char *file = va_arg(*list, const char *); > > + const char *key = va_arg(*list, const char *); > > + Eina_Bool *ret = va_arg(*list, Eina_Bool *); > > + > > + Elm_Image_Smart_Data *sd = _pd; > > + > > + unsigned int i; > > + > > + if (sd->remote) elm_url_cancel(sd->remote); > > + sd->remote = NULL; > > + > > + for (i = 0; i < sizeof (remote_uri) / sizeof (remote_uri[0]); ++i) > > + if (strncmp(remote_uri[i], file, strlen(remote_uri[i])) == 0) > > + { > > + // Found a remote target ! > > + evas_object_hide(sd->img); > > + sd->remote = elm_url_download(file, > > + _elm_image_smart_download_done, > > + > _elm_image_smart_download_cancel, > > + > > _elm_image_smart_download_progress, > > + obj); > > + if (sd->remote) > > + { > > + evas_object_smart_callback_call(obj, SIG_DOWNLOAD_START, > > NULL); > > + eina_stringshare_replace(&sd->key, key); > > + if (ret) *ret = EINA_TRUE; > > + return ; > > + } > > + break; > > + } > > + > > + _elm_image_smart_internal_file_set(obj, sd, file, NULL, key, ret); > > } > > > > EAPI void > > diff --git a/src/lib/elm_image_common.h b/src/lib/elm_image_common.h > > index 7651927..6de250c 100644 > > --- a/src/lib/elm_image_common.h > > +++ b/src/lib/elm_image_common.h > > @@ -19,4 +19,27 @@ typedef enum > > ELM_IMAGE_FLIP_TRANSVERSE = 7 /**< flip the image along the y = x > line > > (top-left to bottom-right) */ > > } Elm_Image_Orient; > > > > +/** > > + * Structure associated with smart callback 'download,progress'. > > + * @since 1.8 > > + */ > > +typedef struct _Elm_Image_Progress Elm_Image_Progress; > > + > > +struct _Elm_Image_Progress > > +{ > > + double now; > > + double total; > > +}; > > + > > + > > +/** > > + * Structre associated with smart callback 'download,error' > > + * @since 1.8 > > + */ > > +typedef struct _Elm_Image_Error Elm_Image_Error; > > +struct _Elm_Image_Error > > +{ > > + int status; > > > > + Eina_Bool open_error; > > +}; > > diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h > > index 212e2ef..6d78e8a 100644 > > --- a/src/lib/elm_priv.h > > +++ b/src/lib/elm_priv.h > > @@ -450,6 +450,18 @@ void > > *_elm_icon_signal_callback_del(Evas_Object *obj, > > Edje_Signal_Cb > > func_cb); > > /* end of DEPRECATED */ > > > > + > > +/* Elm helper to download content */ > > +typedef struct _Elm_Url Elm_Url; > > + > > +typedef void (*Elm_Url_Done)(void *data, Elm_Url *url, Eina_Binbuf > > *download); > > +typedef void (*Elm_Url_Cancel)(void *data, Elm_Url *url, int error); > > +typedef void (*Elm_Url_Progress)(void *data, Elm_Url *url, double now, > > double total); > > + > > +Elm_Url *elm_url_download(const char *url, Elm_Url_Done done_cb, > > Elm_Url_Cancel cancel_cb, Elm_Url_Progress progress_cb, const void > *data); > > +void elm_url_cancel(Elm_Url *r); > > +const char *elm_url_get(Elm_Url *r); > > + > > extern char *_elm_appname; > > extern Elm_Config *_elm_config; > > extern const char *_elm_data_dir; > > diff --git a/src/lib/elm_url.c b/src/lib/elm_url.c > > new file mode 100644 > > index 0000000..2d74561 > > --- /dev/null > > +++ b/src/lib/elm_url.c > > @@ -0,0 +1,147 @@ > > +#ifdef HAVE_CONFIG_H > > +# include "elementary_config.h" > > +#endif > > + > > +#include <Elementary.h> > > +#include "elm_priv.h" > > + > > +struct _Elm_Url > > +{ > > + const char *url; > > + > > + struct { > > + Elm_Url_Done done; > > + Elm_Url_Cancel cancel; > > + Elm_Url_Progress progress; > > + } cb; > > + > > + const void *data; > > + > > + Ecore_Con_Url *target; > > + Eina_Binbuf *download; > > + > > + struct { > > + Ecore_Event_Handler *progress; > > + Ecore_Event_Handler *done; > > + Ecore_Event_Handler *data; > > + } handler; > > +}; > > + > > +static void > > +_elm_url_free(Elm_Url *r) > > +{ > > + ecore_con_url_free(r->target); > > + eina_binbuf_free(r->download); > > + ecore_event_handler_del(r->handler.progress); > > + ecore_event_handler_del(r->handler.done); > > + ecore_event_handler_del(r->handler.data); > > + eina_stringshare_del(r->url); > > + free(r); > > +} > > + > > +static Eina_Bool > > +_elm_url_progress(void *data, int type EINA_UNUSED, void *event) > > +{ > > + Ecore_Con_Event_Url_Progress *url_progress = event; > > + Elm_Url *r = data; > > + > > + if (url_progress->url_con != r->target) return EINA_TRUE; > > + > > + r->cb.progress((void*) r->data, r, url_progress->down.now, > > url_progress->down.total); > > + > > + return EINA_TRUE; > > +} > > + > > +static Eina_Bool > > +_elm_url_done(void *data, int type EINA_UNUSED, void *event) > > +{ > > + Ecore_Con_Event_Url_Complete *url_complete = event; > > + Elm_Url *r = data; > > + > > + if (url_complete->url_con != r->target) return EINA_TRUE; > > + > > + if (url_complete->status == 200) > > + { > > + r->cb.done((void*) r->data, r, r->download); > > + } > > + else > > + { > > + r->cb.cancel((void*) r->data, r, url_complete->status); > > + } > > + > > + _elm_url_free(r); > > + > > + return EINA_TRUE; > > +} > > + > > +static Eina_Bool > > +_elm_url_data(void *data, int type EINA_UNUSED, void *event) > > +{ > > + Ecore_Con_Event_Url_Data *url_data = event; > > + Elm_Url *r = data; > > + > > + if (url_data->url_con != r->target) return EINA_TRUE; > > + > > + eina_binbuf_append_length(r->download, url_data->data, > url_data->size); > > + > > + return EINA_TRUE; > > +} > > + > > +Elm_Url * > > +elm_url_download(const char *url, Elm_Url_Done done_cb, Elm_Url_Cancel > > cancel_cb, Elm_Url_Progress progress_cb, const void *data) > > +{ > > + Ecore_Con_Url *target; > > + Elm_Url *r; > > + > > + ecore_con_url_init(); > > + > > + target = ecore_con_url_new(url); > > + if (!target) goto on_error; > > + > > + if (getenv("http_proxy")) ecore_con_url_proxy_set(target, > > getenv("http_proxy")); > > + if (getenv("https_proxy")) ecore_con_url_proxy_set(target, > > getenv("https_proxy")); > > + if (getenv("ftp_proxy")) ecore_con_url_proxy_set(target, > > getenv("ftp_proxy")); > > + > > + r = malloc(sizeof (Elm_Url)); > > + if (!r) goto on_error; > > + > > + r->url = eina_stringshare_add(url); > > + r->cb.done = done_cb; > > + r->cb.cancel = cancel_cb; > > + r->cb.progress = progress_cb; > > + r->data = data; > > + > > + r->download = eina_binbuf_new(); > > + r->target = target; > > + r->handler.progress = > > ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS, _elm_url_progress, > r); > > + r->handler.done = > > ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _elm_url_done, r); > > + r->handler.data = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA, > > _elm_url_data, r); > > + > > + if (!ecore_con_url_get(r->target)) > > + { > > + _elm_url_free(r); > > + cancel_cb((void*) data, NULL, -1); > > + return NULL; > > + } > > + > > + return r; > > + > > + on_error: > > + ecore_con_url_shutdown(); > > + > > + cancel_cb((void*) data, NULL, -1); > > + return NULL; > > +} > > + > > +void > > +elm_url_cancel(Elm_Url *r) > > +{ > > + r->cb.cancel((void*) r->data, r, 0); > > + _elm_url_free(r); > > +} > > + > > +const char * > > +elm_url_get(Elm_Url *r) > > +{ > > + return r->url; > > +} > > diff --git a/src/lib/elm_widget_image.h b/src/lib/elm_widget_image.h > > index cb4b11e..16ec392 100644 > > --- a/src/lib/elm_widget_image.h > > +++ b/src/lib/elm_widget_image.h > > @@ -33,6 +33,10 @@ struct _Elm_Image_Smart_Data > > Evas_Object *prev_img; > > Ecore_Timer *anim_timer; > > > > + Elm_Url *remote; > > + const char *key; > > + void *remote_data; > > + > > double scale; > > double frame_duration; > > > > > > -- > > > > > > > ------------------------------------------------------------------------------ > > Get 100% visibility into Java/.NET code with AppDynamics Lite! > > It's a free troubleshooting tool designed for production. > > Get down to code-level detail for bottlenecks, with <2% overhead. > > Download for free and get started troubleshooting in minutes. > > > http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk > > > > ------------------------------------------------------------------------------ > Get 100% visibility into Java/.NET code with AppDynamics Lite! > It's a free troubleshooting tool designed for production. > Get down to code-level detail for bottlenecks, with <2% overhead. > Download for free and get started troubleshooting in minutes. > http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk > _______________________________________________ > enlightenment-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >
------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite! It's a free troubleshooting tool designed for production. Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
