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

Reply via email to