This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository efm2.

View the commit online.

commit ce0776c5fb5ea8d88499a7907b3bb3ad8297af84
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Wed May 29 22:09:44 2024 +0100

    add an efm task watcher with super basic ui
    
    thuis starts a task/op/status watcher with a gui that can show tasks
    with progress and some status. status is properly written out.
    scanning and progress is properly calculated. it's beginning to really
    work and be controllable.
---
 src/backends/default/fs.c     |  15 ++-
 src/backends/default/mv.c     |  33 +++++-
 src/backends/default/open.c   |   1 -
 src/backends/default/status.c |  53 ++++++++--
 src/backends/default/status.h |   1 +
 src/efm/efm_back_end.c        |   4 +-
 src/efm/efm_tasks.c           | 238 ++++++++++++++++++++++++++++++++++++++++++
 src/efm/meson.build           |  10 ++
 src/shared/status_mon.c       | 223 +++++++++++++++++++++++++++++++++++++++
 src/shared/status_mon.h       |  17 +++
 10 files changed, 574 insertions(+), 21 deletions(-)

diff --git a/src/backends/default/fs.c b/src/backends/default/fs.c
index affe9b3..2da4b64 100644
--- a/src/backends/default/fs.c
+++ b/src/backends/default/fs.c
@@ -148,6 +148,7 @@ again_write:
                     }
                   else if (ret2 == ret)
                     {
+                      status_pos(ret2, src);
                       off_ou += ret;
                       if (ret < size) break; // end of file
                     }
@@ -171,7 +172,11 @@ again_write:
                       goto err;
                     }
                 }
-              else if (ret < size) break; // end of file
+              else
+                {
+                  status_pos(ret, src);
+                  if (ret < size) break; // end of file
+                }
             }
         }
     }
@@ -433,16 +438,15 @@ fs_mv(const char *src, const char *dst, Eina_Bool report_err)
   int       ret;
   const char *op = "Move";
 
-  status_op("mv");
-  status_count(1, src);
   ret = rename(src, dst);
-  if (ret == 0) return res;
+  if (ret == 0) goto done;
   else
     {
       switch (errno)
         {
         case EXDEV: // revert to cp + rm
-          return fs_cp_rm(src, dst, report_err, EINA_TRUE, EINA_TRUE);
+          res = fs_cp_rm(src, dst, report_err, EINA_TRUE, EINA_TRUE);
+          goto done;
           break;
         default:
           if (report_err) _error_handle(src, dst, op, errno);
@@ -450,6 +454,7 @@ fs_mv(const char *src, const char *dst, Eina_Bool report_err)
           break;
         }
     }
+done:
   status_pos(1, src);
   return res;
 }
diff --git a/src/backends/default/mv.c b/src/backends/default/mv.c
index ff7a44c..e8287ec 100644
--- a/src/backends/default/mv.c
+++ b/src/backends/default/mv.c
@@ -98,6 +98,8 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
   if (!buf) goto err;
 
   status_begin();
+  status_op("mv");
+
   EINA_LIST_FOREACH(files, l, fs)
   {
     struct stat stsrc, stdst;
@@ -113,12 +115,16 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
   {
     fname = ecore_file_file_get(fs->src);
     if (!fname) break;
+    // when monitoring/watching a status file dst dst=xxx allows you to place
+    // progress in the right dst dir
+    status_dst(fs->dst);
     eina_strbuf_reset(buf);
     eina_strbuf_append(buf, fs->dst);
     eina_strbuf_append(buf, "/");
     eina_strbuf_append(buf, fname);
+    // mv the file ...
     if (fs_mv(fs->src, eina_strbuf_string_get(buf), EINA_TRUE))
-      {
+      { // it worked so deal with meta/thumbs
         Eina_Bool   src_can_write, dst_can_write;
         const char *dstfile;
         char       *src_meta, *dst_meta;
@@ -133,15 +139,36 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
         if (dst_can_write) dst_meta = meta_path_find(dstfile, "meta.efm");
         else dst_meta = meta_path_user_find(dstfile, "meta.efm");
         if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
-          fs_mv(src_meta, dst_meta, EINA_FALSE);
+          {
+            status_count(1, src_meta);
+            fs_mv(src_meta, dst_meta, EINA_FALSE);
+            // XXX: how do we force a re-read of the meta file? also how to
+            // merge? e.g. we dnd an icon into a dir - we may or may not at that
+            // point write x,y to the meta file - but we have other fields we
+            // will want to merge in ... so we don't want to mv here - we want
+            // to merge sensibly... so ugh... bug already here ... we want
+            // to also trigger an update of meta data for any efm backends
+            // telling the front-ends...
+          }
         free(src_meta);
         free(dst_meta);
+
         if (src_can_write) src_meta = meta_path_find(fs->src, "thumb.efm");
         else src_meta = meta_path_user_find(fs->src, "thumb.efm");
         if (dst_can_write) dst_meta = meta_path_find(dstfile, "thumb.efm");
         else dst_meta = meta_path_user_find(dstfile, "thumb.efm");
         if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
-          fs_mv(src_meta, dst_meta, EINA_FALSE);
+          {
+            status_count(1, src_meta);
+            fs_mv(src_meta, dst_meta, EINA_FALSE);
+            // XXX: we seem to have any open active re-gen thumbs here as
+            // opposed to use the thumb we mv'd across. we need to do something
+            // like block any thumbnailing while in progress andf tyhen the
+            // thumb has to have its statinfo replaced with valid statinfo
+            // from the new finished cp/mv'd file as its valid... also when
+            // the thumb is finished copying/updating/mvind we need active
+            // opens know to send updates to the views
+          }
         free(src_meta);
         free(dst_meta);
       }
diff --git a/src/backends/default/open.c b/src/backends/default/open.c
index ecce45d..72685cd 100644
--- a/src/backends/default/open.c
+++ b/src/backends/default/open.c
@@ -17,7 +17,6 @@
 #include <pwd.h>
 #include <grp.h>
 
-#include "Ecore_Common.h"
 #include "cmd.h"
 #include "eina_types.h"
 #include "sha.h"
diff --git a/src/backends/default/status.c b/src/backends/default/status.c
index cad830e..08bf315 100644
--- a/src/backends/default/status.c
+++ b/src/backends/default/status.c
@@ -13,6 +13,7 @@
 typedef enum
 {
   MSG_OP,
+  MSG_DST,
   MSG_COUNT,
   MSG_POS,
   MSG_ERR,
@@ -34,6 +35,12 @@ typedef struct
   char *op;
 } Msg_Op;
 
+typedef struct
+{
+  MSG_HEAD;
+  char *dst;
+} Msg_Dst;
+
 typedef struct
 {
   MSG_HEAD;
@@ -66,6 +73,7 @@ static unsigned long long  op_pos        = 0;
 static unsigned long long  op_count_prev = 0;
 static unsigned long long  op_pos_prev   = 0;
 static Eina_Bool           op_end        = EINA_FALSE;
+static Eina_Bool           op_end_prev   = EINA_FALSE;
 static char               *op_str        = NULL;
 static int                 status_fd     = -1;
 static char               *status_file   = NULL;
@@ -91,15 +99,19 @@ _fd_printf(int fd, const char *fmt, ...)
 static void
 _status_flush(void)
 {
-  if ((op_count == op_count_prev) && (op_pos == op_pos_prev)) return;
-  op_count_prev = op_count;
-  op_pos_prev = op_pos;
-  _fd_printf(status_fd, "CMD progress pos=%llu count=%llu\n", op_pos,
-             op_count);
+  if ((op_count == op_count_prev) && (op_pos == op_pos_prev)
+      && (op_end == op_end_prev))
+    return;
+  if ((op_count != op_count_prev) || (op_pos != op_pos_prev))
+    _fd_printf(status_fd, "CMD progress pos=%llu count=%llu\n", op_pos,
+               op_count);
   if (op_str) _fd_printf(status_fd, "CMD progress str=%s\n", op_str);
-  if (op_end) _fd_printf(status_fd, "CMD end\n");
+  if ((op_end) && (op_end != op_end_prev)) _fd_printf(status_fd, "CMD end\n");
   free(op_str);
-  op_str = NULL;
+  op_str        = NULL;
+  op_count_prev = op_count;
+  op_pos_prev   = op_pos;
+  op_end_prev   = op_end;
 }
 
 static void *
@@ -124,11 +136,19 @@ _cb_status_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
           {
             Msg_Op *msg2 = (Msg_Op *)msg;
             // write this out immediately
-            _fd_printf(status_fd, "CMD op %s\n", msg2->op);
-            _fd_printf(status_fd, "CMD pid %i\n", (int)getpid());
+            _fd_printf(status_fd, "CMD op op=%s\n", msg2->op);
+            _fd_printf(status_fd, "CMD pid pid=%i\n", (int)getpid());
             free(msg2->op);
           }
           break;
+        case MSG_DST:
+          {
+            Msg_Dst *msg2 = (Msg_Dst *)msg;
+            // write this out immediately
+            _fd_printf(status_fd, "CMD dst dst=%s\n", msg2->dst);
+            free(msg2->dst);
+          }
+          break;
         case MSG_COUNT:
           {
             Msg_Count *msg2 = (Msg_Count *)msg;
@@ -152,7 +172,7 @@ _cb_status_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
             _fd_printf(status_fd, "CMD error err=%s\n", msg2->str);
             if (msg2->src) _fd_printf(status_fd, "CMD error src="" msg2->src);
             if (msg2->dst) _fd_printf(status_fd, "CMD error dst=%s\n", msg2->dst);
-            _fd_printf(status_fd, "CMD error done\n");
+            _fd_printf(status_fd, "CMD error-done\n");
             free(msg2->src);
             free(msg2->dst);
             free(msg2->str);
@@ -162,6 +182,7 @@ _cb_status_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
           break;
         case MSG_END:
           {
+            op_end = EINA_TRUE;
             _status_flush();
             if (status_fd >= 0)
               {
@@ -229,6 +250,18 @@ status_op(const char *op)
   eina_thread_queue_send_done(status_thq, ref);
 }
 
+void
+status_dst(const char *dst)
+{
+  Msg_Dst *msg;
+  void    *ref;
+
+  msg       = eina_thread_queue_send(status_thq, sizeof(Msg_Dst), &ref);
+  msg->type = MSG_DST;
+  msg->dst   = dst ? escape(dst) : NULL;
+  eina_thread_queue_send_done(status_thq, ref);
+}
+
 void
 status_count(unsigned long long num_inc, const char *str)
 {
diff --git a/src/backends/default/status.h b/src/backends/default/status.h
index 4fd21b2..378ec00 100644
--- a/src/backends/default/status.h
+++ b/src/backends/default/status.h
@@ -24,6 +24,7 @@
 void status_begin(void);
 void status_end(void);
 void status_op(const char *op);
+void status_dst(const char *dst);
 void status_count(unsigned long long num_inc, const char *str);
 void status_pos(unsigned long long pos_inc, const char *str);
 // this call will cause the status thread to report the error then exit(1)
diff --git a/src/efm/efm_back_end.c b/src/efm/efm_back_end.c
index 20d6ef9..c53cc89 100644
--- a/src/efm/efm_back_end.c
+++ b/src/efm/efm_back_end.c
@@ -345,7 +345,7 @@ _icon_add_mod_props_get(Icon *icon, Cmd *c, const char *label)
   eina_stringshare_replace(&(icon->info.label_selected), s);
   s = cmd_key_find(c, "mime");
   if (s) eina_stringshare_replace(&(icon->info.mime), s);
-  if (s) printf("XXXXX   mime=%s\n", icon->info.mime);
+//  if (s) printf("XXXXX   mime=%s\n", icon->info.mime);
   s = cmd_key_find(c, "desktop-icon");
   if (!s) s = cmd_key_find(c, "link-desktop-icon");
   if (s) eina_stringshare_replace(&(icon->info.pre_lookup_icon), s);
@@ -576,7 +576,7 @@ _cb_thread_notify(void *data, Ecore_Thread *th EINA_UNUSED, void *msg)
 
     // below commands all send a path for a specific file
     path = file = cmd_key_find(c, "path");
-    printf("XXXXX [%s] [%s]\n", c->command, file);
+//    printf("XXXXX [%s] [%s]\n", c->command, file);
     if (file)
       {
         s = strrchr(file, '/');
diff --git a/src/efm/efm_tasks.c b/src/efm/efm_tasks.c
new file mode 100644
index 0000000..60c3bb9
--- /dev/null
+++ b/src/efm/efm_tasks.c
@@ -0,0 +1,238 @@
+#include <Elementary.h>
+
+#include "status_mon.h"
+
+static Evas_Object *tasks_box = NULL;
+static Eina_List *tasks = NULL;
+
+typedef struct
+{
+  Status_Op   *op;
+  Evas_Object *o_base, *o_progress, *o_label, *o_label_dst, *o_label_str;
+} Task;
+
+static Task *
+task_find(Status_Op *op)
+{
+  Eina_List *l;
+  Task      *t;
+
+  EINA_LIST_FOREACH(tasks, l, t)
+  {
+    if (t->op == op) return t;
+  }
+  return NULL;
+}
+
+static Task *
+task_add(Status_Op *op)
+{
+  Task *t = calloc(1, sizeof(Task));
+
+  if (!t) return NULL;
+  tasks = eina_list_append(tasks, t);
+  t->op = op;
+  return t;
+}
+
+static void
+task_del(Task *t)
+{
+  Eina_List *l;
+  Task      *t2;
+
+  EINA_LIST_FOREACH(tasks, l, t2)
+  {
+    if (t == t2)
+      {
+        tasks = eina_list_remove(tasks, t);
+        free(t);
+        return;
+      }
+  }
+}
+
+static void
+task_new(Task *t)
+{
+  Evas_Object *o, *bx;
+
+  bx = o = elm_box_add(tasks_box);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_horizontal_set(o, EINA_FALSE);
+  elm_box_pack_end(tasks_box, o);
+  evas_object_show(o);
+  t->o_base = o;
+
+  o = elm_label_add(tasks_box);
+  evas_object_size_hint_fill_set(o, 0, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+  t->o_label = o;
+
+  o = elm_label_add(tasks_box);
+  evas_object_size_hint_fill_set(o, 0, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+  t->o_label_dst = o;
+
+  o = elm_label_add(tasks_box);
+  evas_object_size_hint_fill_set(o, 0, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+  t->o_label_str = o;
+
+  o = elm_progressbar_add(tasks_box);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_progressbar_horizontal_set(o, EINA_TRUE);
+  elm_progressbar_unit_format_set(o, "%1.1f%%");
+  elm_progressbar_span_size_set(o, ELM_SCALE_SIZE(200));
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+  t->o_progress = o;
+}
+
+static void
+_cb_status(void *data EINA_UNUSED, Status_Op *op, Cmd *cmd)
+{
+  Task *t;
+  const char *s, *s2;
+
+  t = task_find(op);
+  if (!t)
+    {
+      t = task_add(op);
+      if (!t) return;
+      task_new(t);
+    }
+  if (!cmd)
+    {
+      evas_object_del(t->o_base);
+      task_del(t);
+      return;
+    }
+  if (!strcmp(cmd->command, "op"))
+    {
+      s = cmd_key_find(cmd, "op");
+      if (s)
+        {
+          if (!strcmp(s, "mv")) elm_object_text_set(t->o_label, "Move");
+        }
+    }
+  else if (!strcmp(cmd->command, "dst"))
+    {
+      s = cmd_key_find(cmd, "dst");
+      if (s)
+        {
+          elm_object_text_set(t->o_label_dst, s);
+        }
+    }
+  else if (!strcmp(cmd->command, "progress"))
+    {
+      s = cmd_key_find(cmd, "str");
+      if (s)
+        {
+          elm_object_text_set(t->o_label_str, s);
+        }
+      s = cmd_key_find(cmd, "pos");
+      if (s)
+        {
+          s2 = cmd_key_find(cmd, "count");
+          if (s2)
+            {
+              unsigned long long pos, count;
+
+              pos = atoll(s);
+              count = atoll(s2);
+
+              if ((pos > 0) && (count > 0))
+                {
+                  double v = (double)pos / (double)count;
+
+                  elm_progressbar_value_set(t->o_progress, v);
+                }
+            }
+        }
+    }
+  else if (!strcmp(cmd->command, "end"))
+    {
+      evas_object_del(t->o_base);
+      task_del(t);
+    }
+  // handle "error"
+}
+
+static void
+_cb_exit(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+  elm_exit();
+}
+
+EAPI_MAIN int
+elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
+{
+  Evas_Object *o, *win, *bx, *sc, *bx2;
+
+  elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+
+  win = o = elm_win_util_standard_add("Main", "Tasks");
+  elm_win_icon_name_set(o, "Tasks");
+  elm_win_role_set(o, "efm_win_tasks");
+  elm_win_autodel_set(o, EINA_TRUE);
+
+  bx = o = elm_box_add(win);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  elm_box_horizontal_set(o, EINA_FALSE);
+  elm_win_resize_object_add(win, o);
+  evas_object_show(o);
+
+  sc = o = elm_scroller_add(win);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+
+  tasks_box = o = elm_box_add(win);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, 0);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_homogeneous_set(o, EINA_TRUE);
+  elm_box_horizontal_set(o, EINA_FALSE);
+  elm_object_content_set(sc, o);
+  evas_object_show(o);
+
+  bx2 = o = elm_box_add(win);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, 0);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_box_homogeneous_set(o, EINA_TRUE);
+  elm_box_horizontal_set(o, EINA_TRUE);
+  elm_box_pack_end(bx, o);
+  evas_object_show(o);
+
+  o = elm_button_add(win);
+  evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, 0);
+  evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0);
+  elm_object_text_set(o, "Exit");
+  evas_object_smart_callback_add(o, "clicked", _cb_exit, NULL);
+  elm_box_pack_end(bx2, o);
+  evas_object_show(o);
+
+  evas_object_resize(win, ELM_SCALE_SIZE(480), ELM_SCALE_SIZE(640));
+  evas_object_show(win);
+
+  status_mon_init();
+  status_mon_callback_add(_cb_status, NULL);
+  status_mon_begin();
+  
+  elm_run();
+
+  status_mon_shutdown();
+
+  return 0;
+}
+ELM_MAIN()
\ No newline at end of file
diff --git a/src/efm/meson.build b/src/efm/meson.build
index e1ded60..08692bd 100644
--- a/src/efm/meson.build
+++ b/src/efm/meson.build
@@ -21,3 +21,13 @@ executable('efm', [
   dependencies: deps,
   install: true,
   install_dir: dir)
+  
+executable('efm_tasks', [
+    '../shared/cmd.c',
+    '../shared/status_mon.c',
+    'efm_tasks.c',
+  ],
+  include_directories: inc,
+  dependencies: deps,
+  install: true,
+  install_dir: dir)
diff --git a/src/shared/status_mon.c b/src/shared/status_mon.c
new file mode 100644
index 0000000..514830e
--- /dev/null
+++ b/src/shared/status_mon.c
@@ -0,0 +1,223 @@
+#include "eina_list.h"
+#include <stdio.h>
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Eina.h>
+#include <Ecore_File.h>
+
+#include "status_mon.h"
+
+struct _Status_Op
+{
+  const char *path;
+  FILE       *file;
+};
+
+typedef struct
+{
+  Status_Mon_Callback  cb;
+  void                *data;
+  Eina_Bool            delete_me : 1;
+} Status_Callback;
+
+static Ecore_File_Monitor *mon = NULL;
+static Eina_List          *ops = NULL;
+static Eina_List          *cbs = NULL;
+static int                 cbs_walk = 0;
+static int                 cbs_del = 0;
+
+static void
+status_callback_clean(void)
+{
+  Eina_List *l, *ll;
+  Status_Callback *sc;
+
+  if ((cbs_walk > 0) || (cbs_del <= 0)) return;
+  EINA_LIST_FOREACH_SAFE(cbs, l, ll, sc)
+  {
+    if (sc->delete_me)
+      {
+        cbs = eina_list_remove_list(cbs, l);
+        free(sc);
+      }
+  }
+  cbs_del = 0;
+}
+
+static Status_Op *
+status_op_add(const char *path)
+{
+  Status_Op *so = calloc(1, sizeof(Status_Op));
+
+  if (!so) return NULL;
+  so->path = eina_stringshare_add(path);
+  so->file = fopen(so->path, "r");
+  ops      = eina_list_append(ops, so);
+  printf("  NEW %p\n", so->file);
+  return so;
+}
+
+static void
+status_op_del(Status_Op *so)
+{
+  ops = eina_list_remove(ops, so);
+  fclose(so->file);
+  eina_stringshare_del(so->path);
+  free(so);
+}
+
+static Status_Op *
+status_op_find(const char *path)
+{
+  Eina_List *l;
+  Status_Op *so;
+
+  EINA_LIST_FOREACH(ops, l, so)
+  {
+    if (!strcmp(so->path, path)) return so;
+  }
+  return NULL;
+}
+
+static void
+status_op_read(Status_Op *so)
+{
+  // XXX: move this to a thread, although these status files SHOULD
+  // be in a ramdisk or cache and thus immediately readable without
+  // any blocking, so i can do this later as an optimmization if needed
+  char buf[PATH_MAX + 256];
+  Cmd *cmd;
+  long pos;
+
+  pos = ftell(so->file);
+  fseek(so->file, pos, SEEK_SET);
+  while (fgets(buf, sizeof(buf), so->file))
+    {
+      size_t sz = strlen(buf);
+
+      if (sz < 1) continue;
+      buf[sz - 1] = 0; // nuke \n
+      printf("  READ CMD [%s]\n", buf);
+      cmd = cmd_parse(buf);
+      if (cmd)
+        {
+          Eina_List       *l;
+          Status_Callback *sc;
+
+          cbs_walk++;
+          EINA_LIST_FOREACH(cbs, l, sc) sc->cb(sc->data, so, cmd);
+          cbs_walk--;
+          status_callback_clean();
+          cmd_free(cmd);
+        }
+    }
+}
+
+static void
+_file_add(const char *path)
+{
+  Status_Op *so;
+
+  fprintf(stderr, "ADD %s\n", path);
+  so = status_op_add(path);
+  if (so) status_op_read(so);
+}
+
+static void
+_file_del(const char *path)
+{
+  Status_Op *so;
+
+  fprintf(stderr, "DEL %s\n", path);
+  so = status_op_find(path);
+  if (so)
+    {
+      Eina_List       *l;
+      Status_Callback *sc;
+
+      cbs_walk++;
+      EINA_LIST_FOREACH(cbs, l, sc) sc->cb(sc->data, so, NULL);
+      cbs_walk--;
+      status_callback_clean();
+      status_op_del(so);
+    }
+}
+
+static void
+_file_mod(const char *path)
+{
+  Status_Op *so;
+
+  fprintf(stderr, "MOD %s\n", path);
+  so = status_op_find(path);
+  if (so) status_op_read(so);
+}
+
+static void
+_cb_mon(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
+        Ecore_File_Event event, const char *path)
+{
+  if ((event == ECORE_FILE_EVENT_CREATED_FILE)
+      || (event == ECORE_FILE_EVENT_CREATED_DIRECTORY))
+    _file_add(path);
+  else if ((event == ECORE_FILE_EVENT_DELETED_FILE)
+      || (event == ECORE_FILE_EVENT_DELETED_DIRECTORY))
+    _file_del(path);
+  else if (event == ECORE_FILE_EVENT_MODIFIED) _file_mod(path);
+}
+
+void status_mon_init(void)
+{
+}
+
+void
+status_mon_callback_add(Status_Mon_Callback cb, void *data)
+{
+  Status_Callback *sc = calloc(1, sizeof(Status_Callback));
+
+  if (!sc) return;
+  sc->cb = cb;
+  sc->data = ""
+  cbs = eina_list_append(cbs, sc);
+}
+
+void
+status_mon_callback_del(Status_Mon_Callback cb, void *data)
+{
+  Eina_List *l;
+  Status_Callback *sc;
+
+  EINA_LIST_FOREACH(cbs, l, sc)
+  {
+    if ((cb == sc->cb) && (data == sc->data))
+      {
+        if (cbs_walk <= 0)
+          {
+            cbs = eina_list_remove_list(cbs, l);
+            free(sc);
+          }
+        else
+          {
+            sc->delete_me = EINA_TRUE;
+            cbs_del++;
+          }
+        break;
+      }
+  }
+}
+
+void
+status_mon_begin(void)
+{
+  char buf[PATH_MAX];
+
+  eina_vpath_resolve_snprintf(buf, sizeof(buf), "(:usr.run:)/efm/ops");
+  ecore_file_mkpath(buf);
+  mon = ecore_file_monitor_add(buf, _cb_mon, NULL);
+}
+
+void status_mon_shutdown(void)
+{
+  if (mon) ecore_file_monitor_del(mon);
+  mon = NULL;
+}
\ No newline at end of file
diff --git a/src/shared/status_mon.h b/src/shared/status_mon.h
new file mode 100644
index 0000000..9ec833b
--- /dev/null
+++ b/src/shared/status_mon.h
@@ -0,0 +1,17 @@
+#ifndef STATUS_MON_H
+#define STATUS_MON_H
+
+#include <Eina.h>
+#include "cmd.h"
+
+typedef struct _Status_Op Status_Op;
+
+typedef void (*Status_Mon_Callback) (void *data, Status_Op *op, Cmd *cmd);
+
+void status_mon_init(void);
+void status_mon_callback_add(Status_Mon_Callback cb, void *data);
+void status_mon_callback_del(Status_Mon_Callback cb, void *data);
+void status_mon_begin(void);
+void status_mon_shutdown(void);
+
+#endif
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to