billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=76e9ae6481d968d489aa694e810ca4798a9dcf38

commit 76e9ae6481d968d489aa694e810ca4798a9dcf38
Author: Boris Faure <bill...@gmail.com>
Date:   Sun Feb 15 20:32:16 2015 +0100

    do an HTTP HEAD to get media type when poping media
---
 data/themes/default.edc |  72 ++++++++++++++++++++
 src/bin/media.c         |  19 ++++++
 src/bin/media.h         |   1 +
 src/bin/termio.c        |  16 +----
 src/bin/win.c           | 176 ++++++++++++++++++++++++++++++++++++++++++++----
 src/bin/win.h           |   2 +
 6 files changed, 260 insertions(+), 26 deletions(-)

diff --git a/data/themes/default.edc b/data/themes/default.edc
index 165e179..1d0eb46 100644
--- a/data/themes/default.edc
+++ b/data/themes/default.edc
@@ -225,6 +225,8 @@ collections {
         image: "tab_shad_l1.png" COMP;
         image: "tab_shad_r0.png" COMP;
         image: "tab_shad_r1.png" COMP;
+        image: "media_busy_knob.png" COMP;
+        image: "media_busy_spinner.png" COMP;
       }
       set { name: "bg_shadow";
         image { image: "bg_shadow.png"  COMP; size: 0 0 200 150; }
@@ -1618,6 +1620,76 @@ collections {
             target: "popmedia_glintclip";
             target: "popmedia_shine";
          }
+
+         /* media busy */
+         part { name: "media"; type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "knob";
+            clip_to: "media";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               image.normal: "media_busy_knob.png";
+               min: 40 40;
+               max: 40 40;
+               align: 1.0 1.0;
+            }
+         }
+         part { name: "knob_spinner";
+            clip_to: "media";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               color: 51 153 255 255;
+               rel1.to: "knob";
+               rel2.to: "knob";
+               image.normal: "media_busy_spinner.png";
+               map {
+                  on: 1;
+                  smooth: 1;
+                  rotation.center: "knob";
+               }
+            }
+            description { state: "spin" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               map.rotation.z: 360;
+            }
+         }
+         program {
+            signal: "busy"; source: "terminology";
+            action: STATE_SET "visible" 0.0;
+            transition: DECELERATE 0.5;
+            target: "media";
+         }
+         program { name: "spin1";
+            signal: "busy"; source: "terminology";
+            action: STATE_SET "spin" 0.0;
+            transition: LINEAR 0.5;
+            target: "knob_spinner";
+            after: "spin2";
+         }
+         program { name: "spin2";
+            action: STATE_SET "default" 0.0;
+            target: "knob_spinner";
+            after: "spin1";
+         }
+         program {
+            signal: "done"; source: "terminology";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 1.5;
+            target: "media";
+         }
       }
    }
 
diff --git a/src/bin/media.c b/src/bin/media.c
index c0bfc26..c0ed0d0 100644
--- a/src/bin/media.c
+++ b/src/bin/media.c
@@ -1426,3 +1426,22 @@ media_control_get(Evas_Object *obj)
    if (!sd) return NULL;
    return sd->o_ctrl;
 }
+
+void
+media_unknown_handle(const char *handler, const char *src)
+{
+   const char *cmd;
+   char buf[PATH_MAX];
+   char *escaped;
+
+   cmd = "xdg-open";
+   escaped = ecore_file_escape_name(src);
+   if (!escaped)
+     return;
+   if (handler && *handler)
+     cmd = handler;
+   snprintf(buf, sizeof(buf), "%s %s", cmd, escaped);
+   free(escaped);
+
+   ecore_exe_run(buf, NULL);
+}
diff --git a/src/bin/media.h b/src/bin/media.h
index 8b5d082..48b5c16 100644
--- a/src/bin/media.h
+++ b/src/bin/media.h
@@ -38,5 +38,6 @@ void media_stop(Evas_Object *obj);
 const char *media_get(const Evas_Object *obj);
 Media_Type media_src_type_get(const char *src);
 Evas_Object *media_control_get(Evas_Object *obj);
+void media_unknown_handle(const char *handler, const char *src);
 
 #endif
diff --git a/src/bin/termio.c b/src/bin/termio.c
index 0414ffa..789c314 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -833,20 +833,8 @@ _activate_link(Evas_Object *obj, Eina_Bool may_inline)
              type = media_src_type_get(sd->link.string);
              if (may_inline && _should_inline(obj))
                {
-                  if ((type == MEDIA_TYPE_IMG) ||
-                      (type == MEDIA_TYPE_SCALE) ||
-                      (type == MEDIA_TYPE_EDJE))
-                    {
-                       // XXX: begin fetch of url, once done, show
-                       evas_object_smart_callback_call(obj, "popup", NULL);
-                       handled = EINA_TRUE;
-                    }
-                  else if (type == MEDIA_TYPE_MOV)
-                    {
-                       // XXX: if no http:// add
-                       evas_object_smart_callback_call(obj, "popup", NULL);
-                       handled = EINA_TRUE;
-                    }
+                  evas_object_smart_callback_call(obj, "popup", NULL);
+                  handled = EINA_TRUE;
                }
              if (!handled)
                {
diff --git a/src/bin/win.c b/src/bin/win.c
index 6de4db8..f6a4124 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -56,6 +56,7 @@ struct _Term
    struct {
       int       x, y;
    } down;
+   int refcnt;
    unsigned char focused : 1;
    unsigned char hold : 1;
    unsigned char unswallowed : 1;
@@ -363,7 +364,7 @@ win_free(Win *wn)
    wins = eina_list_remove(wins, wn);
    EINA_LIST_FREE(wn->terms, term)
      {
-        term_free(term);
+        term_unref(term);
      }
    if (wn->cmdbox_del_timer)
      {
@@ -542,7 +543,7 @@ main_close(Evas_Object *win, Evas_Object *term)
           }
         l = eina_list_data_find_list(sp->terms, tm);
         _term_resize_track_stop(sp);
-        term_free(tm);
+        term_unref(tm);
         if (l)
           {
              if (tm == sp->term)
@@ -601,7 +602,7 @@ main_close(Evas_Object *win, Evas_Object *term)
         _term_resize_track_stop(sp);
         edje_object_part_unswallow(sp->wn->base, sp->term->bg);
         l = eina_list_data_find_list(sp->terms, tm);
-        term_free(tm);
+        term_unref(tm);
         if (l)
           {
              if (tm == sp->term)
@@ -1541,18 +1542,17 @@ _cb_media_loop(void *data, Evas_Object *obj 
EINA_UNUSED, void *info EINA_UNUSED)
 }
 
 static void
-_popmedia_show(Term *term, const char *src)
+_popmedia_show(Term *term, const char *src, Media_Type type)
 {
    Evas_Object *o;
    Config *config = termio_config_get(term->term);
-   Media_Type type;
 
-   if (!config) return;
+   EINA_SAFETY_ON_NULL_RETURN(config);
    ty_dbus_link_hide();
    if (term->popmedia)
      {
         const char *s;
-        
+
         EINA_LIST_FREE(term->popmedia_queue, s)
           {
              eina_stringshare_del(s);
@@ -1563,7 +1563,6 @@ _popmedia_show(Term *term, const char *src)
         return;
      }
    termio_mouseover_suspend_pushpop(term->term, 1);
-   type = media_src_type_get(src);
    term->popmedia = o = media_add(win_evas_object_get(term->wn),
                                   src, config, MEDIA_POP, type);
    term->popmedia_deleted = EINA_FALSE;
@@ -1592,6 +1591,142 @@ _popmedia_show(Term *term, const char *src)
      }
 }
 
+/* TODO: XXX: should be s/13/14 */
+#define HAVE_ECORE_CON_URL_HTTP_HEAD \
+   ((ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 13))
+
+#if HAVE_ECORE_CON_URL_HTTP_HEAD
+typedef struct _Ty_Http_Head {
+     const char *handler;
+     const char *src;
+     Ecore_Con_Url *url;
+     Ecore_Event_Handler *url_complete;
+     Term *term;
+} Ty_Http_Head;
+
+static void
+_ty_http_head_delete(Ty_Http_Head *ty_head)
+{
+   eina_stringshare_del(ty_head->handler);
+   eina_stringshare_del(ty_head->src);
+   ecore_con_url_free(ty_head->url);
+   ecore_event_handler_del(ty_head->url_complete);
+   edje_object_signal_emit(ty_head->term->bg, "done", "terminology");
+   term_unref(ty_head->term);
+
+   free(ty_head);
+}
+
+static Eina_Bool
+_media_http_head_complete(void *data, int kind EINA_UNUSED, void *event_info)
+{
+   Ecore_Con_Event_Url_Complete *ev = event_info;
+   Ty_Http_Head *ty_head = data;
+   const Eina_List *headers, *l;
+   Media_Type type = MEDIA_TYPE_UNKNOWN;
+   char *str;
+
+   if (ev->status != 200)
+     goto error;
+   headers = ecore_con_url_response_headers_get(ev->url_con);
+   EINA_LIST_FOREACH(headers, l, str)
+     {
+#define  _CONTENT_TYPE_HDR "Content-Type: "
+#define  _LOCATION_HDR "Location: "
+        if (!strncmp(str, _LOCATION_HDR, strlen(_LOCATION_HDR)))
+          {
+             unsigned int len;
+
+             str += strlen(_LOCATION_HDR);
+             eina_stringshare_del(ty_head->src);
+
+             /* skip the crlf */
+             len = strlen(str);
+             if (len <= 2)
+               goto error;
+
+             ty_head->src = eina_stringshare_add_length(str, len - 2);
+             if (!ty_head->src)
+               goto error;
+          }
+        else if (!strncmp(str, _CONTENT_TYPE_HDR, strlen(_CONTENT_TYPE_HDR)))
+          {
+             str += strlen(_CONTENT_TYPE_HDR);
+             if (!strncmp(str, "image/", strlen("image/")))
+               {
+                  type = MEDIA_TYPE_IMG;
+               }
+             else if (!strncmp(str, "video/", strlen("video/")))
+               {
+                  type = MEDIA_TYPE_MOV;
+               }
+             if (type != MEDIA_TYPE_UNKNOWN)
+               {
+                  _popmedia_show(ty_head->term, ty_head->src, type);
+                  break;
+               }
+          }
+#undef _CONTENT_TYPE_HDR
+#undef _LOCATION_HDR
+     }
+
+   _ty_http_head_delete(ty_head);
+   return EINA_TRUE;
+error:
+   media_unknown_handle(ty_head->handler, ty_head->src);
+   _ty_http_head_delete(ty_head);
+   return EINA_TRUE;
+}
+#endif
+
+static void
+_popmedia(Term *term, const char *src)
+{
+   Media_Type type;
+   Config *config = termio_config_get(term->term);
+
+#if HAVE_ECORE_CON_URL_HTTP_HEAD
+   Ty_Http_Head *ty_head = calloc(1, sizeof(Ty_Http_Head));
+   if (!ty_head)
+     return;
+
+   if (config->helper.local.general && config->helper.local.general[0])
+     {
+        ty_head->handler = eina_stringshare_add(config->helper.local.general);
+        if (!ty_head->handler)
+          goto error;
+     }
+   ty_head->src = eina_stringshare_add(src);
+   if (!ty_head->src)
+     goto error;
+   ty_head->url = ecore_con_url_new(src);
+   if (!ty_head->url)
+     goto error;
+   if (!ecore_con_url_head(ty_head->url))
+     goto error;
+   ty_head->url_complete = ecore_event_handler_add
+      (ECORE_CON_EVENT_URL_COMPLETE, _media_http_head_complete, ty_head);
+   if (!ty_head->url_complete)
+     goto error;
+   ty_head->term = term;
+   edje_object_signal_emit(term->bg, "busy", "terminology");
+   term_ref(term);
+
+   return;
+
+error:
+   _ty_http_head_delete(ty_head);
+#endif
+
+   type = media_src_type_get(src);
+   if (type == MEDIA_TYPE_UNKNOWN) {
+        media_unknown_handle(config->helper.local.general, src);
+   } else {
+        _popmedia_show(term, src, type);
+   }
+}
+
+
 static void
 _term_miniview_check(Term *term)
 {
@@ -1657,7 +1792,7 @@ _popmedia_queue_process(Term *term)
    term->popmedia_queue = eina_list_remove_list(term->popmedia_queue, 
                                                 term->popmedia_queue);
    if (!src) return;
-   _popmedia_show(term, src);
+   _popmedia(term, src);
    eina_stringshare_del(src);
 }
 
@@ -1676,7 +1811,7 @@ _cb_popup(void *data, Evas_Object *obj EINA_UNUSED, void 
*event)
    const char *src = event;
    if (!src) src = termio_link_get(term->term);
    if (!src) return;
-   _popmedia_show(term, src);
+   _popmedia(term, src);
 }
 
 static void
@@ -1733,7 +1868,7 @@ _cb_command(void *data, Evas_Object *obj EINA_UNUSED, 
void *event)
      {
         if (cmd[1] == 'n') // now
           {
-             _popmedia_show(term, cmd + 2);
+             _popmedia(term, cmd + 2);
           }
         else if (cmd[1] == 'q') // queue it to display after current one
           {
@@ -2601,6 +2736,22 @@ _cb_exited(void *data, Evas_Object *obj EINA_UNUSED, 
void *event EINA_UNUSED)
      }
 }
 
+void
+term_ref(Term *term)
+{
+   term->refcnt++;
+}
+
+void term_unref(Term *term)
+{
+   EINA_SAFETY_ON_NULL_RETURN(term);
+
+   term->refcnt--;
+   if (term->refcnt <= 0)
+     {
+        term_free(term);
+     }
+}
 
 Term *
 term_new(Win *wn, Config *config, const char *cmd,
@@ -2611,9 +2762,10 @@ term_new(Win *wn, Config *config, const char *cmd,
    Evas_Object *o;
    Evas *canvas = evas_object_evas_get(wn->win);
    Edje_Message_Int msg;
-   
+
    term = calloc(1, sizeof(Term));
    if (!term) return NULL;
+   term_ref(term);
 
    if (!config) abort();
 
diff --git a/src/bin/win.h b/src/bin/win.h
index fc2b0b1..e4e4507 100644
--- a/src/bin/win.h
+++ b/src/bin/win.h
@@ -40,6 +40,8 @@ void win_term_swallow(Win *wn, Term *term);
 void win_add_split(Win *wn, Term *term);
 void win_sizing_handle(Win *wn);
 
+void term_ref(Term *term);
+void term_unref(Term *term);
 Term *term_next_get(Term *term);
 Term *term_prev_get(Term *term);
 void term_next(Term *term);

-- 


Reply via email to