emotion: restore/save last know position for file.
authorcedric <cedric>
Wed, 29 Jun 2011 17:30:19 +0000 (17:30 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 29 Jun 2011 17:30:19 +0000 (17:30 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/emotion@60825 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/bin/emotion_test_main.c
src/lib/Emotion.h
src/lib/Makefile.am
src/lib/emotion_smart.c

index 88c1bd6..bfddc57 100644 (file)
@@ -177,6 +177,28 @@ case "$host_os" in
 esac
 AC_SUBST(lt_enable_auto_import)
 
+### Check for extended attribute
+
+AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(
+       [[
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+       ]],
+       [[
+size_t tmp = listxattr("/", NULL, 0);
+tmp = getxattr("/", "user.ethumb.md5", NULL, 0);
+setxattr("/", "user.ethumb.md5", NULL, 0, 0);
+       ]])],
+    [
+      AC_DEFINE(HAVE_XATTR, 1, [Define to 1 if you have 'listxattr', 'setxattr' and 'getxattr'])
+      have_xattr="yes"
+    ],
+    [have_xattr="no"])
+
+AC_MSG_CHECKING([for Xattr])
+AC_MSG_RESULT([${have_xattr}])
 
 ### Modules
 
@@ -192,6 +214,18 @@ if test "x${enable_xine}" = "xno" && test "x${enable_gstreamer}" = "xno"; then
    AC_MSG_ERROR([Xine or Gstreamer backends must be selected to build Emotion])
 fi
 
+PKG_CHECK_MODULES([EIO],
+       [eio],
+       [
+        have_eio="yes"
+        AC_DEFINE(HAVE_EIO, 1, [Use EIO for asynchronous file access])
+        requirement_emotion="eio ${requirement_emotion}"
+       ],
+       [have_eio="no"])
+
+AM_CONDITIONAL([HAVE_EIO], [test "x${have_eio}" = "xyes"])
+
+
 AC_SUBST(requirement_emotion)
 
 #disabled vlc
@@ -234,6 +268,9 @@ echo "  edje_cc..............: ${edje_cc}"
 echo
 echo "  Edje EXTERNAL support: ${have_edje_external}"
 echo
+echo "  Xattr................: ${have_xattr}"
+echo "  Eio..................: ${have_eio}"
+echo
 echo "Compilation............: make (or gmake)"
 echo "  CPPFLAGS.............: $CPPFLAGS"
 echo "  CFLAGS...............: $CFLAGS"
index 9625e88..f7902a2 100644 (file)
@@ -77,13 +77,13 @@ main_resize(Ecore_Evas *ee)
 static Eina_Bool
 main_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__)
 {
+   Evas_Object *o;
+
    ecore_main_loop_quit();
-   while (video_objs)
+   EINA_LIST_FREE(video_objs, o)
      {
-       printf("del obj!\n");
-       evas_object_del(video_objs->data);
-       video_objs = eina_list_remove_list(video_objs, video_objs);
-       printf("done\n");
+       emotion_object_last_position_save(o);
+       evas_object_del(o);
      }
    return EINA_TRUE;
 }
@@ -564,6 +564,7 @@ init_video_object(const char *module_filename, const char *filename)
      {
        return;
      }
+   emotion_object_last_position_load(o);
    emotion_object_play_set(o, 1);
    evas_object_move(o, 0, 0);
    evas_object_resize(o, 320, 240);
index 9a2b4f8..f841537 100644 (file)
@@ -174,6 +174,9 @@ EAPI void         emotion_object_vis_set               (Evas_Object *obj, Emotio
 EAPI Emotion_Vis  emotion_object_vis_get               (const Evas_Object *obj);
 EAPI Eina_Bool    emotion_object_vis_supported         (const Evas_Object *obj, Emotion_Vis visualization);
 
+EAPI void         emotion_object_last_position_load    (Evas_Object *obj);
+EAPI void         emotion_object_last_position_save    (Evas_Object *obj);
+
 EAPI Eina_Bool    emotion_object_extension_can_play_get(const Evas_Object *obj, const char *file);
 EAPI Eina_Bool    emotion_object_extension_can_play_fast_get(const Evas_Object *obj, const char *file);
 
index 96eabdd..cf2dadc 100644 (file)
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
 -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
 @EMOTION_CPPFLAGS@ \
 @EMOTION_CFLAGS@ \
+@EIO_CFLAGS@ \
 @EFL_EMOTION_BUILD@
 
 if EMOTION_STATIC_BUILD_XINE
@@ -46,7 +47,7 @@ libemotion_la_SOURCES += \
 $(top_srcdir)/src/modules/vlc/emotion_vlc.c
 endif
 
-libemotion_la_LIBADD = @EMOTION_LIBS@
+libemotion_la_LIBADD = @EMOTION_LIBS@ @EIO_LIBS@
 
 if EMOTION_STATIC_BUILD_XINE
 libemotion_la_LIBADD += @XINE_LIBS@
index c9451d3..c84d60c 100644 (file)
@@ -2,9 +2,11 @@
 #include "Emotion.h"
 
 #ifdef HAVE_EIO
+# include <math.h>
 # include <Eio.h>
 #else
 # ifdef HAVE_XATTR
+#  include <math.h>
 #  include <sys/xattr.h>
 # endif
 #endif
@@ -45,6 +47,7 @@ typedef struct _Smart_Data Smart_Data;
 
 struct _Smart_Data
 {
+   EINA_REFCOUNT;
    Emotion_Video_Module  *module;
    void                  *video;
 
@@ -80,6 +83,8 @@ struct _Smart_Data
 #ifdef HAVE_EIO
    Eio_File *load_xattr;
    Eio_File *save_xattr;
+
+   const char *time_seek;
 #endif
 
    Emotion_Module_Options module_options;
@@ -172,16 +177,45 @@ _emotion_image_data_zero(Evas_Object *img)
    evas_object_image_data_set(img, data);
 }
 
+static void
+_emotion_module_close(Emotion_Video_Module *mod, void *video)
+{
+   if (!mod) return;
+   if (mod->plugin->close && video)
+     mod->plugin->close(mod, video);
+   /* FIXME: we can't go dlclosing here as a thread still may be running from
+    * the module - this in theory will leak- but it shouldnt be too bad and
+    * mean that once a module is dlopened() it cant be closed - its refcount
+    * will just keep going up
+    */
+}
+
+static void
+_smart_data_free(Smart_Data *sd)
+{
+   if (sd->video) sd->module->file_close(sd->video);
+   _emotion_module_close(sd->module, sd->video);
+   evas_object_del(sd->obj);
+   eina_stringshare_del(sd->file);
+   free(sd->module_name);
+   if (sd->job) ecore_job_del(sd->job);
+   free(sd->progress.info);
+   free(sd->ref.file);
+   free(sd);
+
+   ecore_shutdown();
+}
+
 EAPI Eina_Bool
-_emotion_module_register(const char *name, Emotion_Module_Open open, Emotion_Module_Close close)
+_emotion_module_register(const char *name, Emotion_Module_Open mod_open, Emotion_Module_Close mod_close)
 {
    Eina_Emotion_Plugins *plugin;
 
    plugin = malloc(sizeof (Eina_Emotion_Plugins));
    if (!plugin) return EINA_FALSE;
 
-   plugin->open = open;
-   plugin->close = close;
+   plugin->open = mod_open;
+   plugin->close = mod_close;
 
    return eina_hash_add(_backends, name, plugin);
 }
@@ -241,19 +275,6 @@ _emotion_module_open(const char *name, Evas_Object *obj, Emotion_Video_Module **
    return NULL;
 }
 
-static void
-_emotion_module_close(Emotion_Video_Module *mod, void *video)
-{
-   if (!mod) return;
-   if (mod->plugin->close && video)
-     mod->plugin->close(mod, video);
-   /* FIXME: we can't go dlclosing here as a thread still may be running from
-    * the module - this in theory will leak- but it shouldnt be too bad and
-    * mean that once a module is dlopened() it cant be closed - its refcount
-    * will just keep going up
-    */
-}
-
 /*******************************/
 /* Externally accessible calls */
 /*******************************/
@@ -315,8 +336,6 @@ emotion_object_init(Evas_Object *obj, const char *module_filename)
    sd->seek_pos = 0;
    sd->len = 0;
 
-   ecore_init();
-
    _emotion_module_close(sd->module, sd->video);
    sd->module = NULL;
    sd->video = NULL;
@@ -1002,6 +1021,147 @@ emotion_object_vis_supported(const Evas_Object *obj, Emotion_Vis visualization)
    return sd->module->vis_supported(sd->video, visualization);
 }
 
+#ifdef HAVE_EIO
+static void
+_eio_load_xattr_cleanup(Smart_Data *sd)
+{
+   sd->load_xattr = NULL;
+
+   EINA_REFCOUNT_UNREF(sd)
+     _smart_data_free(sd);
+}
+
+static void
+_eio_load_xattr_done(void *data, Eio_File *handler __UNUSED__, const char *xattr_data, unsigned int xattr_size)
+{
+   Smart_Data *sd = data;
+
+   if (xattr_size < 128 && xattr_data[xattr_size] == '\0')
+     {
+        long long int m = 0;
+        long int e = 0;
+
+        eina_convert_atod(xattr_data, xattr_size, &m, &e);
+        emotion_object_position_set(evas_object_smart_parent_get(sd->obj), ldexp((double)m, e));
+     }
+
+   _eio_load_xattr_cleanup(sd);
+}
+
+static void
+_eio_load_xattr_error(void *data, Eio_File *handler __UNUSED__, int err __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   _eio_load_xattr_cleanup(sd);
+}
+#endif
+
+EAPI void
+emotion_object_last_position_load(Evas_Object *obj)
+{
+   Smart_Data *sd;
+   const char *tmp;
+
+   E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+   if (!sd->file) return ;
+
+   if (!strncmp(sd->file, "file://", 7))
+     tmp = sd->file + 7;
+   else if (!strstr(sd->file, "://"))
+     tmp = sd->file;
+   else
+     return ;
+
+#ifdef HAVE_EIO
+   if (sd->load_xattr) return ;
+
+   EINA_REFCOUNT_REF(sd);
+
+   sd->load_xattr = eio_file_xattr_get(tmp, "user.e.time_seek", _eio_load_xattr_done, _eio_load_xattr_error, sd);
+#else
+# ifdef HAVE_XATTR
+   {
+      char double_to_string[128];
+      ssize_t sz;
+      long long int m = 0;
+      long int e = 0;
+
+      sz = getxattr(tmp, "user.e.time_seek", double_to_string, 128);
+      if (sz <= 0 || sz > 128 || double_to_string[sz] != '\0')
+        return ;
+
+      eina_convert_atod(double_to_string, 128, &m, &e);
+      emotion_object_position_set(obj, ldexp((double)m, e));
+   }
+# endif
+#endif
+}
+
+#ifdef HAVE_EIO
+static void
+_eio_save_xattr_cleanup(Smart_Data *sd)
+{
+   sd->save_xattr = NULL;
+   eina_stringshare_del(sd->time_seek);
+   sd->time_seek = NULL;
+
+   EINA_REFCOUNT_UNREF(sd)
+     _smart_data_free(sd);
+}
+
+static void
+_eio_save_xattr_done(void *data, Eio_File *handler __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   _eio_save_xattr_cleanup(sd);
+}
+
+static void
+_eio_save_xattr_error(void *data, Eio_File *handler __UNUSED__, int err __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   _eio_save_xattr_cleanup(sd);
+}
+#endif
+
+EAPI void
+emotion_object_last_position_save(Evas_Object *obj)
+{
+   Smart_Data *sd;
+   const char *tmp;
+   char double_to_string[128];
+
+   E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+   if (!sd->file) return ;
+
+   if (!strncmp(sd->file, "file://", 7))
+     tmp = sd->file + 7;
+   else if (!strstr(sd->file, "://"))
+     tmp = sd->file;
+   else
+     return ;
+
+   eina_convert_dtoa(emotion_object_position_get(obj), double_to_string);
+
+#ifdef HAVE_EIO
+   if (sd->save_xattr) return ;
+
+   EINA_REFCOUNT_REF(sd);
+
+   sd->time_seek = eina_stringshare_add(double_to_string);
+   sd->save_xattr = eio_file_xattr_set(tmp, "user.e.time_seek",
+                                       sd->time_seek, eina_stringshare_strlen(sd->time_seek) + 1, 0,
+                                       _eio_save_xattr_done, _eio_save_xattr_error, sd);
+#else
+# ifdef HAVE_XATTR
+   setxattr(tmp, "user.e.time_seek", double_to_string, strlen(double_to_string), 0);
+# endif
+#endif
+}
+
 EAPI Eina_Bool
 emotion_object_extension_can_play_fast_get(const Evas_Object *obj, const char *file)
 {
@@ -1257,14 +1417,14 @@ _emotion_title_set(Evas_Object *obj, char *title)
 }
 
 EAPI void
-_emotion_progress_set(Evas_Object *obj, char *info, double stat)
+_emotion_progress_set(Evas_Object *obj, char *info, double st)
 {
    Smart_Data *sd;
 
    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
    free(sd->progress.info);
    sd->progress.info = strdup(info);
-   sd->progress.stat = stat;
+   sd->progress.stat = st;
    evas_object_smart_callback_call(obj, SIG_PROGRESS_CHANGE, NULL);
 }
 
@@ -1581,6 +1741,7 @@ _smart_add(Evas_Object * obj)
 
    sd = calloc(1, sizeof(Smart_Data));
    if (!sd) return;
+   EINA_REFCOUNT_INIT(sd);
    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, sd);
    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, sd);
@@ -1596,6 +1757,8 @@ _smart_add(Evas_Object * obj)
        evas_object_image_data_set(obj, pixel);
      }
    evas_object_smart_data_set(obj, sd);
+
+   ecore_init();
 }
 
 static void
@@ -1605,17 +1768,8 @@ _smart_del(Evas_Object * obj)
 
    sd = evas_object_smart_data_get(obj);
    if (!sd) return;
-   if (sd->video) sd->module->file_close(sd->video);
-   _emotion_module_close(sd->module, sd->video);
-   evas_object_del(sd->obj);
-   eina_stringshare_del(sd->file);
-   free(sd->module_name);
-   if (sd->job) ecore_job_del(sd->job);
-   free(sd->progress.info);
-   free(sd->ref.file);
-   free(sd);
-
-   ecore_shutdown();
+   EINA_REFCOUNT_UNREF(sd)
+     _smart_data_free(sd);
 }
 
 static void