diff --git a/TODO b/TODO index 5b1fa2f..944721a 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,5 @@ * volume status display when changed (slider/image/percentage) * emotion engine selection options (gui) -* timeline thumbnails on position slider * right click control panel (ala terminology - need elm config ui code) * about display/popup (from panel?) * mouse wheel for forward/rewind and/or prev/next and/or volume up/down @@ -13,4 +12,4 @@ * show busy anim until opened cb or failure * add button/control top-left next to audio to do fullscreen/normal toggle * detect letterboxing and auto-crop - +* thumbnail picker show all thumbs for video in a grid to select position diff --git a/data/themes/default.edc b/data/themes/default.edc index f3ea3e6..5aaa1dc 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -35,6 +35,10 @@ collections { images.image: "horizontal_separated_bar_small_glow.png" COMP; images.image: "vgrad_shadow_bi.png" COMP; + images.image: "win_shadow.png" COMP; + images.image: "bg_shine.png" COMP; + images.image: "bg_glint.png" COMP; + set { name: "pos_indicator"; image { image: "pos_indicator_big.png" COMP; size: 32 28 99999 99999; } image { image: "pos_indicator.png" COMP; size: 0 0 31 27; } @@ -61,6 +65,7 @@ collections { script { public pos_visible; public pos_timer; + public drag_is_down; public pos_timeout(val) { set_int(pos_visible, 0); @@ -1261,6 +1266,212 @@ collections { } } + part { name: "dragover_master"; type: RECT; + clip_to: "posclip"; + description { state: "default" 0.0; + visible: 1; + } + description { state: "novideo" 0.0; + visible: 0; + } + } + program { + signal: "state,novideo"; source: "rage"; + action: STATE_SET "novideo" 0.0; + target: "dragover_master"; + } + program { + signal: "state,video"; source: "rage"; + action: STATE_SET "default" 0.0; + target: "dragover_master"; + } + part { name: "dragover_active"; type: RECT; + clip_to: "dragover_master"; + description { state: "default" 0.0; + color: 255 255 255 0; + visible: 0; + } + description { state: "visible" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + part { name: "dragover_event"; type: RECT; repeat_events: 1; + clip_to: "posclip"; + description { state: "default" 0.0; + rel1.to_x: "bar_bg"; + rel1.to_y: "posevent"; + rel2.to_x: "bar_bg"; + color: 0 0 0 0; + fixed: 1 1; + } + } + program { + signal: "mouse,in"; source: "dragover_event"; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.5; + target: "dragover_active"; + } + program { + signal: "mouse,out"; source: "dragover_event"; + action: STATE_SET "default" 0.0; + transition: SINUSOIDAL 1.0; + target: "dragover_active"; + } + part { name: "dragover"; type: SPACER; + description { state: "default" 0.0; + rel1.to: "dragover_event"; + rel1.relative: 0.5 0.0; + rel2.to: "dragover_event"; + rel2.relative: 0.5 0.0; + fixed: 1 1; + } + } + part { name: "dragshadow"; mouse_events: 0; + clip_to: "dragover_active"; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "rage.dragable.content"; + rel2.to: "rage.dragable.content"; + image.normal: "win_shadow.png"; + image.border: 14 14 14 14; + image.middle: 0; + rel1.offset: -7 -3; + rel2.offset: 6 11; + fill.smooth: 0; + } + } + part { name: "dragover_fill"; mouse_events: 0; + clip_to: "dragover_active"; + description { state: "default" 0.0; + fixed: 1 1; + image.normal: "pm_fill.png"; + fill { + size.relative: 0.0 0.0; + size.offset: 64 64; + } + rel1.to: "rage.dragable.content"; + rel2.to: "rage.dragable.content"; + } + } + part { name: "rage.dragable.content"; type: SWALLOW; + clip_to: "dragover_active"; + description { state: "default" 0.0; + rel1.to: "dragover"; + rel2.to: "dragover"; + align: 0.5 1.0; + fixed: 1 1; + } + } + part { name: "dragover_clip"; type: RECT; + clip_to: "dragover_active"; + description { state: "default" 0.0; + rel1.to: "rage.dragable.content"; + rel2.to: "rage.dragable.content"; + fixed: 1 1; + } + } + part { name: "dragover_glintclip"; type: RECT; + clip_to: "dragover_active"; + description { state: "default" 0.0; + rel1.to: "dragover_clip"; + rel2.to: "dragover_clip"; + rel1.offset: 0 -10; + } + } + part { name: "shine"; mouse_events: 0; + clip_to: "dragover_clip"; + description { state: "default" 0.0; + image.normal: "bg_shine.png"; + fill.smooth: 0; + rel1.to: "dragover_clip"; + rel2.to: "dragover_clip"; + align: 0.5 0.0; + aspect: (255/120) (255/120); + aspect_preference: HORIZONTAL; + } + } + part { name: "glint"; mouse_events: 0; + clip_to: "dragover_glintclip"; + description { state: "default" 0.0; + fixed: 1 1; + min: 79 5; + max: 79 5; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "dragover_clip"; + } + rel2 { + relative: 1.0 0.0; + offset: -1 0; + to: "dragover_clip"; + } + image.normal: "bg_glint.png"; + } + } + part { name: "dragover_bevel2"; + clip_to: "dragover_active"; + description { state: "default" 0.0; + image.normal: "bg_bevel.png"; + image.border: 1 1 1 1; + image.middle: 0; + fill.smooth: 0; + rel1.to: "rage.dragable.content"; + rel2.to: "rage.dragable.content"; + } + } + program { name: "dragmove"; + signal: "mouse,move"; source: "dragover_event"; + script { + new mx, my, x, y, w, h; + new Float:pos, Float:px, Float:pw; + + get_mouse(mx, my); + get_geometry(PART:"dragover_event", x, y, w, h); + x = mx - x; + y = my - y; + px = x; + pw = w; + if (w > 0) pos = px / pw; + else pos = 0.5; + custom_state(PART:"dragover", "default", 0.0); + set_state_val(PART:"dragover", STATE_REL1, pos, 0.0); + set_state_val(PART:"dragover", STATE_REL2, pos, 0.0); + set_state(PART:"dragover", "custom", 0.0); + send_message(MSG_FLOAT, 13, pos); + if (get_int(drag_is_down) == 1) + send_message(MSG_FLOAT, 10, pos); + } + } + program { name: "dragdown"; + signal: "mouse,down,1"; source: "dragover_event"; + script { + new mx, my, x, y, w, h; + new Float:pos, Float:px, Float:pw; + + set_int(drag_is_down, 1); + get_mouse(mx, my); + get_geometry(PART:"dragover_event", x, y, w, h); + x = mx - x; + y = my - y; + px = x; + pw = w; + if (w > 0) pos = px / pw; + else pos = 0.5; + custom_state(PART:"dragover", "default", 0.0); + set_state_val(PART:"dragover", STATE_REL1, pos, 0.0); + set_state_val(PART:"dragover", STATE_REL2, pos, 0.0); + set_state(PART:"dragover", "custom", 0.0); + send_message(MSG_FLOAT, 10, pos); + } + } + program { name: "dragup"; + signal: "mouse,up,1"; source: "dragover_event"; + script { + set_int(drag_is_down, 0); + } + } part { name: "event"; type: RECT; repeat_events: 1; description { state: "default" 0.0; color: 0 0 0 0; diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 479d5ab..bc92fe4 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -20,7 +20,8 @@ winvid.c winvid.h \ win.c win.h \ winlist.c winlist.h \ config.c config.h \ -sha1.c sha1.h +sha1.c sha1.h \ +videothumb.c videothumb.h internal_bindir = $(libdir)/rage/utils internal_bin_PROGRAMS = rage_thumb diff --git a/src/bin/key.c b/src/bin/key.c index 8d24ee3..a33ac67 100644 --- a/src/bin/key.c +++ b/src/bin/key.c @@ -9,8 +9,7 @@ void key_handle(Evas_Object *win, Evas_Event_Key_Down *ev) { Inf *inf = evas_object_data_get(win, "inf"); - - printf("%s | %s\n", ev->key, ev->keyname); + if ((!strcmp(ev->key, "Left")) || (!strcmp(ev->key, "bracketleft"))) { @@ -20,7 +19,7 @@ key_handle(Evas_Object *win, Evas_Event_Key_Down *ev) else { double pos = video_position_get(inf->vid); - + if (!inf->last_action_rwind) { double t = ecore_time_get(); @@ -161,7 +160,7 @@ key_handle(Evas_Object *win, Evas_Event_Key_Down *ev) else if (!strcmp(ev->keyname, "n")) { int w, h; - + video_ratio_size_get(inf->vid, &w, &h); if ((w > 1) && (h > 1)) evas_object_resize(win, w, h); } diff --git a/src/bin/main.c b/src/bin/main.c index 58d01e5..7f6ae4f 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -32,7 +32,8 @@ elm_main(int argc, char **argv) int i; Inf *inf; Config *config; - + + elm_need_efreet(); config_init(); config = config_get(); for (i = 1; i < argc; i++) @@ -62,7 +63,7 @@ elm_main(int argc, char **argv) else list = eina_list_append(list, eina_stringshare_add(argv[i])); } - + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR); elm_app_compile_data_dir_set(PACKAGE_DATA_DIR); @@ -78,11 +79,11 @@ elm_main(int argc, char **argv) win = win_add(); evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _cb_resize, NULL); evas_object_resize(win, 320, 200); - + win_video_init(win); win_video_file_list_set(win, list); EINA_LIST_FREE(list, f) eina_stringshare_del(f); - + inf = evas_object_data_get(win, "inf"); if (argc <= 1) { @@ -94,7 +95,7 @@ elm_main(int argc, char **argv) { inf->show_timeout = ecore_timer_add(10.0, _cb_show_timeout, win); } - + elm_run(); config_shutdown(); diff --git a/src/bin/thumb.c b/src/bin/thumb.c index 397ac9f..11a7aa1 100644 --- a/src/bin/thumb.c +++ b/src/bin/thumb.c @@ -63,7 +63,6 @@ elm_main(int argc, char **argv) char key[128]; snprintf(key, sizeof(key), "%i", pos); - pos += incr; evas_object_image_file_set(vidimage, argv[1], key); evas_object_image_size_get(vidimage, &iw, &ih); if ((iw <= 0) || (ih <= 0)) break; @@ -75,10 +74,10 @@ elm_main(int argc, char **argv) elm_win_render(subwin); pixels = evas_object_image_data_get(image, EINA_FALSE); if (pixels) - { - eet_data_image_write(ef, key, pixels, w, h, - 0, 0, 70, EET_IMAGE_JPEG); - } + eet_data_image_write(ef, key, pixels, w, h, + 0, 0, 70, EET_IMAGE_JPEG); + else + exit(6); evas_object_image_data_set(image, pixels); } eet_close(ef); diff --git a/src/bin/video.c b/src/bin/video.c index 500e6a5..3ac4f0f 100644 --- a/src/bin/video.c +++ b/src/bin/video.c @@ -472,6 +472,14 @@ video_file_set(Evas_Object *obj, const char *file) video_position_set(obj, 0.0); } +const char * +video_file_get(Evas_Object *obj) +{ + Video *sd = evas_object_smart_data_get(obj); + if (!sd) return NULL; + return sd->file; +} + void video_mute_set(Evas_Object *obj, Eina_Bool mute) { diff --git a/src/bin/video.h b/src/bin/video.h index be644f0..8257520 100644 --- a/src/bin/video.h +++ b/src/bin/video.h @@ -5,6 +5,7 @@ Evas_Object *video_add(Evas_Object *parent); void video_file_set(Evas_Object *obj, const char *file); +const char *video_file_get(Evas_Object *obj); void video_mute_set(Evas_Object *obj, Eina_Bool mute); Eina_Bool video_mute_get(Evas_Object *obj); void video_play_set(Evas_Object *obj, Eina_Bool play); diff --git a/src/bin/videothumb.c b/src/bin/videothumb.c new file mode 100644 index 0000000..8d41f5b --- /dev/null +++ b/src/bin/videothumb.c @@ -0,0 +1,382 @@ +#include +#include "videothumb.h" +#include "sha1.h" + +typedef struct _Videothumb Videothumb; + +struct _Videothumb +{ + Evas_Object_Smart_Clipped_Data __clipped_data; + Evas_Object *o_img; + Ecore_Exe *thumb_exe; + Ecore_Event_Handler *exe_handler; + const char *file; + const char *realfile; + double pos; + unsigned int realpos; + int iw, ih; + Evas_Coord w, h; + Eina_Bool seen : 1; +}; + +static Evas_Smart *_smart = NULL; +static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL; + +static Eina_List *busy_thumbs = NULL; +static Eina_List *vidthumbs = NULL; + +static Eina_Bool +_busy_add(const char *file) +{ + Eina_List *l; + const char *s; + + EINA_LIST_FOREACH(busy_thumbs, l, s) + { + if (!strcmp(file, s)) return EINA_FALSE; + } + busy_thumbs = eina_list_append(busy_thumbs, eina_stringshare_add(file)); + return EINA_TRUE; +} + +static Eina_Bool +_busy_del(const char *file) +{ + Eina_List *l; + const char *s; + + EINA_LIST_FOREACH(busy_thumbs, l, s) + { + if (!strcmp(file, s)) + { + eina_stringshare_del(s); + busy_thumbs = eina_list_remove_list(busy_thumbs, l); + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +static void +_thumb_update(Evas_Object *obj) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + char buf[PATH_MAX]; + + if (!sd) return; + snprintf(buf, sizeof(buf), "%u", sd->realpos); + evas_object_image_file_set(sd->o_img, NULL, NULL); + evas_object_image_file_set(sd->o_img, sd->realfile, buf); + evas_object_image_size_get(sd->o_img, &(sd->iw), &(sd->ih)); + if ((sd->iw <= 0) || (sd->ih <= 0)) + { + evas_object_del(sd->o_img); + sd->o_img = NULL; + evas_object_smart_callback_call(obj, "failed", NULL); + } + else + { + evas_object_image_preload(sd->o_img, EINA_FALSE); + evas_object_smart_callback_call(obj, "loaded", NULL); + } +} + +static void +_thumb_match_update(Evas_Object *obj, const char *file) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + + if (!sd) return; + if (!strcmp(sd->file, file)) _thumb_update(obj); +} + +static Eina_Bool +_cb_thumb_exe(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Exe_Event_Del *ev; + Videothumb *sd = evas_object_smart_data_get(data); + + if (!sd) return EINA_TRUE; + ev = event; + if (ev->exe == sd->thumb_exe) + { + Eina_List *l; + Evas_Object *o; + + _busy_del(sd->file); + EINA_LIST_FOREACH(vidthumbs, l, o) _thumb_match_update(o, sd->file); + if ((sd->iw <= 0) || (sd->ih <= 0)) + { + if (sd->exe_handler) + { + ecore_event_handler_del(sd->exe_handler); + sd->exe_handler = NULL; + } + } + sd->thumb_exe = NULL; + return EINA_FALSE; + } + return EINA_TRUE; +} + +static void +_cb_preload(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED) +{ + Videothumb *sd = evas_object_smart_data_get(data); + + if (!sd) return; + evas_object_show(sd->o_img); + evas_object_smart_callback_call(data, "data", NULL); +} + +static void +_videothumb_image_load(Evas_Object *obj) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + char buf_base[PATH_MAX]; + char buf_file[PATH_MAX]; + char buf[PATH_MAX]; + char *s; + const char *libdir; + unsigned char sum[20]; + + if (!sd) return; + if (!sd->file) return; + sd->o_img = evas_object_image_filled_add(evas_object_evas_get(obj)); + evas_object_smart_member_add(sd->o_img, obj); + if (!sha1((unsigned char *)sd->file, strlen(sd->file), sum)) return; + snprintf(buf_base, sizeof(buf_base), "%s/rage/thumb/%02x", + efreet_cache_home_get(), sum[0]); + snprintf(buf_file, sizeof(buf_base), + "%s/%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x.eet", + buf_base, + sum[1], sum[2], sum[3], + sum[4], sum[5], sum[6], sum[7], + sum[8], sum[9], sum[10], sum[11], + sum[12], sum[13], sum[14], sum[15], + sum[16], sum[17], sum[18], sum[19]); + if (sd->realfile) eina_stringshare_del(sd->realfile); + sd->realfile = eina_stringshare_add(buf_file); + sd->realpos = (((unsigned int)(sd->pos * 1000.0)) / 10000) * 10000; + snprintf(buf, sizeof(buf), "%u", sd->realpos); + evas_object_event_callback_add(sd->o_img, + EVAS_CALLBACK_IMAGE_PRELOADED, + _cb_preload, obj); + evas_object_image_file_set(sd->o_img, sd->realfile, buf); + evas_object_image_size_get(sd->o_img, &(sd->iw), &(sd->ih)); + if (sd->iw > 0) + { + Eina_Bool ok = EINA_FALSE; + struct stat st1, st2; + + if (stat(sd->file, &st1) == 0) + { + if (stat(sd->realfile, &st2) == 0) + { + if (st1.st_mtime < st2.st_mtime) ok = EINA_TRUE; + } + } + if (ok) + { + evas_object_image_preload(sd->o_img, EINA_FALSE); + return; + } + } + if (!_busy_add(sd->file)) return; + ecore_exe_run_priority_set(10); + if (sd->thumb_exe) + { + ecore_exe_free(sd->thumb_exe); + sd->thumb_exe = NULL; + } + s = ecore_file_escape_name(sd->file); + if (s) + { + libdir = elm_app_lib_dir_get(); + if (libdir) + { + if (!sd->exe_handler) + sd->exe_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _cb_thumb_exe, obj); + snprintf(buf, sizeof(buf), + "%s/rage/utils/rage_thumb %s 10000 >& /dev/null", + libdir, s); + sd->thumb_exe = ecore_exe_pipe_run(buf, + ECORE_EXE_TERM_WITH_PARENT | + ECORE_EXE_NOT_LEADER, + obj); + } + } +} + +static void +_videothumb_eval(Evas_Object *obj, Eina_Bool force) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + Evas_Coord ox, oy, ow, oh, vw, vh; + Eina_Bool seen = EINA_FALSE; + + if (!sd) return; + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + evas_output_viewport_get(evas_object_evas_get(obj), NULL, NULL, &vw, &vh); + // XXX: not listening to canvas resizes! :( + if (ELM_RECTS_INTERSECT(ox, oy, ow, oh, 0, 0, vw, vh)) seen = EINA_TRUE; + // XXX: fix - wrokaround and always visible + seen = EINA_TRUE; + if (force) + { + sd->seen = seen; + if (sd->o_img) + { + evas_object_del(sd->o_img); + sd->o_img = NULL; + } + _videothumb_image_load(obj); + evas_object_move(sd->o_img, ox, oy); + evas_object_resize(sd->o_img, ow, oh); + } + else + { + if (seen != sd->seen) + { + sd->seen = seen; + if (sd->seen) + { + if (sd->o_img) + { + evas_object_del(sd->o_img); + sd->o_img = NULL; + } + _videothumb_image_load(obj); + evas_object_move(sd->o_img, ox, oy); + evas_object_resize(sd->o_img, ow, oh); + } + else + { + if (sd->o_img) + { + evas_object_del(sd->o_img); + sd->o_img = NULL; + } + } + } + } +} + +static void +_smart_add(Evas_Object *obj) +{ + Videothumb *sd; + + sd = calloc(1, sizeof(Videothumb)); + EINA_SAFETY_ON_NULL_RETURN(sd); + evas_object_smart_data_set(obj, sd); + _parent_sc.add(obj); +} + +static void +_smart_del(Evas_Object *obj) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + if (!sd) return; + vidthumbs = eina_list_remove(vidthumbs, obj); + if (sd->file) eina_stringshare_del(sd->file); + if (sd->realfile) eina_stringshare_del(sd->realfile); + if (sd->o_img) evas_object_del(sd->o_img); + if (sd->thumb_exe) ecore_exe_free(sd->thumb_exe); + if (sd->exe_handler) ecore_event_handler_del(sd->exe_handler); + _parent_sc.del(obj); +} + +static void +_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + Evas_Coord ox, oy, ow, oh; + if (!sd) return; + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + if ((ow == w) && (oh == h)) return; + evas_object_smart_changed(obj); +} + +static void +_smart_calculate(Evas_Object *obj) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + Evas_Coord ox, oy, ow, oh; + + if (!sd) return; + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + sd->w = ow; + sd->h = oh; + _videothumb_eval(obj, EINA_FALSE); + if (sd->o_img) + { + evas_object_move(sd->o_img, ox, oy); + evas_object_resize(sd->o_img, ow, oh); + } +} + +static void +_smart_move(Evas_Object *obj, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + if (!sd) return; + evas_object_smart_changed(obj); +} + +static void +_smart_init(void) +{ + static Evas_Smart_Class sc; + + evas_object_smart_clipped_smart_set(&_parent_sc); + sc = _parent_sc; + sc.name = "videothumb"; + sc.version = EVAS_SMART_CLASS_VERSION; + sc.add = _smart_add; + sc.del = _smart_del; + sc.resize = _smart_resize; + sc.move = _smart_move; + sc.calculate = _smart_calculate; + _smart = evas_smart_class_new(&sc); +} + +Evas_Object * +videothumb_add(Evas_Object *parent) +{ + Evas *e; + Evas_Object *obj; + + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + e = evas_object_evas_get(parent); + if (!e) return NULL; + if (!_smart) _smart_init(); + obj = evas_object_smart_add(e, _smart); + vidthumbs = eina_list_prepend(vidthumbs, obj); + return obj; +} + +void +videothumb_file_set(Evas_Object *obj, const char *file, double pos) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + if (!sd) return; + if ((sd->file == file) && (sd->pos == pos)) return; + if (sd->file) eina_stringshare_del(sd->file); + sd->file = eina_stringshare_add(file); + sd->pos = pos; + _videothumb_eval(obj, EINA_TRUE); +} + +void +videothumb_size_get(Evas_Object *obj, int *w, int *h) +{ + Videothumb *sd = evas_object_smart_data_get(obj); + *w = 1; + *h = 1; + if (!sd) return; + *w = sd->iw; + *h = sd->ih; +} diff --git a/src/bin/videothumb.h b/src/bin/videothumb.h new file mode 100644 index 0000000..ce0029a --- /dev/null +++ b/src/bin/videothumb.h @@ -0,0 +1,8 @@ +#ifndef _VIDEOTHUMB_H__ +#define _VIDEOTHUMB_H__ 1 + +Evas_Object *videothumb_add(Evas_Object *parent); +void videothumb_file_set(Evas_Object *obj, const char *file, double pos); +void videothumb_size_get(Evas_Object *obj, int *w, int *h); + +#endif diff --git a/src/bin/win.c b/src/bin/win.c index 988ace1..d356099 100644 --- a/src/bin/win.c +++ b/src/bin/win.c @@ -138,7 +138,7 @@ win_do_next(Evas_Object *win) { double pos = video_position_get(inf->vid); double len = video_length_get(inf->vid); - + if ((len - pos) > 5.0) { video_position_set(inf->vid, len - 5.0); @@ -198,7 +198,7 @@ win_video_prev(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l; - + if (!inf->file_list) return; if (!inf->file_cur) l = eina_list_last(inf->file_list); else l = inf->file_cur->prev; @@ -213,7 +213,7 @@ win_video_first(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l; - + if (!inf->file_list) return; l = inf->file_list; inf->file_cur = l; @@ -226,7 +226,7 @@ win_video_last(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l; - + if (!inf->file_list) return; l = eina_list_last(inf->file_list); if (!l) return; @@ -240,7 +240,7 @@ win_video_have_next(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l; - + if (!inf->file_list) return EINA_FALSE; if (!inf->file_cur) return EINA_FALSE; else l = inf->file_cur->next; @@ -253,7 +253,7 @@ win_video_have_prev(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l; - + if (!inf->file_list) return EINA_FALSE; if (!inf->file_cur) return EINA_FALSE; else l = inf->file_cur->prev; @@ -269,19 +269,19 @@ win_add(void) Inf *inf = calloc(1, sizeof(Inf)); if (!inf) return NULL; - + win = elm_win_add(NULL, "Rage", ELM_WIN_BASIC); if (!win) return NULL; - + elm_win_title_set(win, "Rage"); elm_win_autodel_set(win, EINA_TRUE); - + evas_object_data_set(win, "inf", inf); evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cb_win_del, NULL); evas_object_smart_callback_add(win, "fullscreen", _cb_fullscreen, NULL); evas_object_smart_callback_add(win, "unfullscreen", _cb_unfullscreen, NULL); evas_object_smart_callback_add(win, "normal", _cb_unfullscreen, NULL); - + o = evas_object_image_add(evas_object_evas_get(win)); snprintf(buf, sizeof(buf), "%s/images/rage.png", elm_app_data_dir_get()); evas_object_image_file_set(o, buf, NULL); @@ -295,7 +295,7 @@ win_add(void) evas_object_show(o); inf->lay = o; controls_init(win, o); - + o = evas_object_rectangle_add(evas_object_evas_get(win)); evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, o); @@ -334,7 +334,7 @@ win_title_update(Evas_Object *win) Inf *inf = evas_object_data_get(win, "inf"); const char *file, *s; char buf[4096]; - + if (!inf->file_cur) { elm_win_title_set(win, "Rage"); @@ -393,7 +393,7 @@ win_aspect_adjust(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); int w = 1, h = 1; - + video_ratio_size_get(inf->vid, &w, &h); if (inf->zoom_mode == 1) evas_object_size_hint_aspect_set(inf->vid, EVAS_ASPECT_CONTROL_NEITHER, @@ -415,6 +415,6 @@ void win_frame_decode(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); - + controls_update(inf->lay, inf->vid); } diff --git a/src/bin/win.h b/src/bin/win.h index 43ec07a..6967f78 100644 --- a/src/bin/win.h +++ b/src/bin/win.h @@ -5,7 +5,7 @@ typedef struct _Inf Inf; struct _Inf { - Evas_Object *vid, *lay, *event, *event2, *glayer; + Evas_Object *vid, *lay, *event, *event2, *glayer, *vidthumb; Eina_List *file_list, *file_cur; Ecore_Job *next_job; Ecore_Timer *show_timeout; diff --git a/src/bin/winvid.c b/src/bin/winvid.c index 4f55e61..e93d53c 100644 --- a/src/bin/winvid.c +++ b/src/bin/winvid.c @@ -4,6 +4,7 @@ #include "video.h" #include "winlist.h" #include "winvid.h" +#include "videothumb.h" static void _cb_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) @@ -30,7 +31,6 @@ static void _cb_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Inf *inf = evas_object_data_get(data, "inf"); - printf("stop\n"); if (win_video_have_next(data)) { if (inf->next_job) ecore_job_del(inf->next_job); @@ -42,7 +42,6 @@ _cb_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) static void _cb_opened(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("opened\n"); win_aspect_adjust(data); win_frame_decode(data); win_title_update(data); @@ -51,7 +50,6 @@ _cb_opened(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) static void _cb_length(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("len\n"); win_frame_decode(data); win_title_update(data); } @@ -59,21 +57,18 @@ _cb_length(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) static void _cb_title(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("title\n"); win_title_update(data); } static void _cb_audio(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("audio\n"); win_title_update(data); } static void _cb_channels(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("channels\n"); win_title_update(data); } @@ -81,7 +76,6 @@ static void _cb_play_start(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Inf *inf = evas_object_data_get(data, "inf"); - printf("play start\n"); win_aspect_adjust(data); win_frame_decode(data); win_title_update(data); @@ -92,7 +86,6 @@ static void _cb_play_finish(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Inf *inf = evas_object_data_get(data, "inf"); - printf("play finish\n"); if (!inf->playing) win_show(data, 160, 160); inf->playing = EINA_FALSE; } @@ -100,23 +93,75 @@ _cb_play_finish(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSE static void _cb_button_num(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("button num\n"); win_title_update(data); } static void _cb_button(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { - printf("button\n"); win_title_update(data); } +static void +_cb_vidthumb_loaded(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + Inf *inf = evas_object_data_get(data, "inf"); + + if (!inf) return; +} + +static void +_cb_vidthumb_failed(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + Inf *inf = evas_object_data_get(data, "inf"); + + if (!inf) return; +} + +static void +_cb_vidthumb_data(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + int w, h; + Inf *inf = evas_object_data_get(data, "inf"); + + if (!inf) return; + videothumb_size_get(inf->vidthumb, &w, &h); + w = ((double)w * elm_config_scale_get()) / 2.0; + h = ((double)h * elm_config_scale_get()) / 2.0; + evas_object_size_hint_min_set(inf->vidthumb, w, h); +} + +static void +_cb_layout_message(void *data, Evas_Object *obj EINA_UNUSED, Edje_Message_Type type, int id, void *msg) +{ + Inf *inf = evas_object_data_get(data, "inf"); + + if (!inf) return; + if (type == EDJE_MESSAGE_FLOAT) + { + if (id == 10) + { + Edje_Message_Float *m = msg; + double len = video_length_get(inf->vid); + video_position_set(inf->vid, len * m->val); + } + else if (id == 13) + { + Edje_Message_Float *m = msg; + double len = video_length_get(inf->vid); + videothumb_file_set(inf->vidthumb, video_file_get(inf->vid), + len * m->val); + } + } +} + void win_video_init(Evas_Object *win) { Inf *inf = evas_object_data_get(win, "inf"); Evas_Object *o; - + Evas_Coord sz; + o = video_add(win); video_fill_set(o, EINA_TRUE); inf->vid = o; @@ -134,6 +179,19 @@ win_video_init(Evas_Object *win) evas_object_smart_callback_add(o, "button", _cb_button, win); elm_object_part_content_set(inf->lay, "rage.content", o); evas_object_show(o); + + o = videothumb_add(win); + inf->vidthumb = o; + evas_object_smart_callback_add(o, "loaded", _cb_vidthumb_loaded, win); + evas_object_smart_callback_add(o, "failed", _cb_vidthumb_failed, win); + evas_object_smart_callback_add(o, "data", _cb_vidthumb_data, win); + sz = 80; + sz = (double)sz * elm_config_scale_get(); + evas_object_size_hint_min_set(o, sz, sz); + elm_object_part_content_set(inf->lay, "rage.dragable.content", o); + evas_object_show(o); + edje_object_message_handler_set(elm_layout_edje_get(inf->lay), + _cb_layout_message, win); } void @@ -142,7 +200,7 @@ win_video_file_list_set(Evas_Object *win, Eina_List *list) Inf *inf = evas_object_data_get(win, "inf"); Eina_List *l, *list2 = NULL; const char *f; - + EINA_LIST_FOREACH(list, l, f) { list2 = eina_list_append(list2, eina_stringshare_add(f)); @@ -155,7 +213,7 @@ void win_video_insert(Evas_Object *win, const char *file) { Inf *inf = evas_object_data_get(win, "inf"); - + inf->file_list = eina_list_append_relative_list (inf->file_list, eina_stringshare_add(file), inf->file_cur); evas_object_data_set(win, "file_list", inf->file_list);