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); --