discomfitor pushed a commit to branch master.

http://git.enlightenment.org/apps/empc.git/commit/?id=8936365d19a42e8e150ff98c50f178ca11820722

commit 8936365d19a42e8e150ff98c50f178ca11820722
Author: Mike Blumenkrantz <[email protected]>
Date:   Thu Dec 25 21:06:03 2014 -0500

    hugely beef up apm module
    
    * auto-insert new adds into existing albums
    
    * check database info if shitty filesystem organization exists
---
 src/modules/Makefile.mk             |   2 +
 src/modules/auto_playlist_manager.c | 246 +++++++++++++++++++++++++++++++++---
 2 files changed, 232 insertions(+), 16 deletions(-)

diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk
index e6f3d1b..ff50952 100644
--- a/src/modules/Makefile.mk
+++ b/src/modules/Makefile.mk
@@ -233,12 +233,14 @@ src_modules_auto_playlist_manager_la_CPPFLAGS = \
 $(AM_CFLAGS) \
 $(mod_cppflags) \
 @EFL_CFLAGS@ \
+@ELM_CFLAGS@ \
 @EIO_CFLAGS@ \
 -I$(top_srcdir)/src/bin \
 -I$(top_builddir)
 
 src_modules_auto_playlist_manager_la_LIBADD = \
 @EFL_LIBS@ \
+@ELM_LIBS@ \
 @EIO_LIBS@
 
 src_modules_auto_playlist_manager_la_LDFLAGS = -module -avoid-version
diff --git a/src/modules/auto_playlist_manager.c 
b/src/modules/auto_playlist_manager.c
index 65ca274..4870ad8 100644
--- a/src/modules/auto_playlist_manager.c
+++ b/src/modules/auto_playlist_manager.c
@@ -2,12 +2,12 @@
 # include "config.h"
 #endif
 
-#define EMPC_EXTERNS_ONLY
 
 #include "empdd.h"
 #include "empc.h"
 #include <Ecore.h>
 #include <Eio.h>
+#include <Elementary.h>
 #include "eldbus_empd_empdd.h"
 
 static Eina_Stringshare *log_file;
@@ -15,6 +15,10 @@ static Eio_Monitor *log_monitor;
 static Eina_List *handlers;
 static size_t log_size;
 static Eina_Bool log_dirty;
+static Ecore_Timer *update_timer;
+
+static Eina_List *adds;
+static unsigned int wait_count;
 
 static void auto_playlist_manager_shutdown(void);
 
@@ -44,6 +48,7 @@ log_removed(void *d EINA_UNUSED, int t EINA_UNUSED, 
Eio_Monitor_Event *ev)
 static Eina_Bool
 log_modified(void *d EINA_UNUSED, int t EINA_UNUSED, Eio_Monitor_Event *ev)
 {
+   if (!master) return ECORE_CALLBACK_RENEW;
    if (ev->filename != log_file) return ECORE_CALLBACK_RENEW;
    log_dirty = EINA_TRUE;
    return ECORE_CALLBACK_RENEW;
@@ -71,15 +76,197 @@ sort_cb(const char *a, const char *b)
    return strcmp(a, b);
 }
 
+static inline Eina_Bool
+is_same_path(const char *a, const char *ae, const char *b, const char *be)
+{
+   if (!ae)
+     {
+        ae = strrchr(a, '/');
+        if (ae) ae++;
+     }
+   if (!be)
+     {
+        be = strrchr(b, '/');
+        if (be) be++;
+     }
+   if (ae - a != be - b) return EINA_FALSE;
+   return !memcmp(a, b, ae - a);
+}
+
+static void
+info_cb(Eldbus_Proxy *proxy EINA_UNUSED, void *data, Eldbus_Pending *pending 
EINA_UNUSED, Eldbus_Error_Info *error EINA_UNUSED, Eina_Value *args)
+{
+   Eina_Value array;
+   unsigned int i;
+
+   if (!args) return; //canceled
+   eina_value_struct_value_get(args, "arg0", &array);
+   for (i = 0; i < eina_value_array_count(&array); i++)
+     {
+        Eina_Value struc, val, realval;
+        int type;
+        Empd_Empdd_File *file = NULL;
+
+        eina_value_array_value_get(&array, i, &struc);
+        eina_value_struct_get(&struc, "arg0", &type);
+        eina_value_struct_value_get(&struc, "arg1", &val);
+        eina_value_struct_value_get(&val, "arg0", &realval);
+        switch (type)
+          {
+           case MPD_ENTITY_TYPE_DIRECTORY:
+           case MPD_ENTITY_TYPE_PLAYLIST:
+             break;
+           case MPD_ENTITY_TYPE_SONG:
+             if (azy_value_to_Empd_Empdd_File(&realval, &file))
+               {
+                  const Eina_List *l, *ll;
+                  Elm_Object_Item *it;
+                  Empd_Empdd_Song *so;
+
+                  l = empc_modapi_queue_list_header_items_find(file->artist, 
file->album);
+                  if (!l)
+                    {
+                       /* no match: append */
+                       empd_empdd_add_list_call(empd_proxy, data);
+                       wait_count++;
+                       break;
+                    }
+                  if (!file->track)
+                    {
+                       so = eina_list_last_data_get(l);
+                       empd_empdd_add_id_list_call(empd_proxy, data, 
so->song_pos + 1);
+                       break;
+                    }
+                  /* matches: insert at end point first to avoid breaking song 
positions */
+                  EINA_LIST_REVERSE_FOREACH(l, ll, it)
+                    {
+                       const Eina_List *sl, *sll;
+                       Elm_Object_Item *sit;
+
+                       sl = elm_genlist_item_subitems_get(it);
+                       if (eina_list_count(sl) < 2) continue; //ignore single 
songs
+                       wait_count++;
+                       EINA_LIST_FOREACH(sl, sll, sit)
+                         {
+                            so = elm_object_item_data_get(sit);
+                            if (so->track > file->track)
+                              {
+                                 empd_empdd_add_id_list_call(empd_proxy, data, 
so->song_pos);
+                                 break;
+                              }
+                            if (!sll->next)
+                              empd_empdd_add_id_list_call(empd_proxy, data, 
so->song_pos + 1);
+                         }
+                    }
+               }
+             break;
+          }
+        eina_value_flush(&struc);
+        eina_value_flush(&val);
+        eina_value_flush(&realval);
+     }
+   eina_value_flush(&array);
+   free(data);
+}
+
+static void
+run_adds(void)
+{
+   char *file;
+   Eina_List *l, *ll;
+
+   EINA_LIST_FOREACH_SAFE(adds, l, ll, file)
+     {
+        const char *a, *b = NULL;
+        Eina_Iterator *it;
+        Eina_List *i, *ii;
+        Elm_Object_Item *item;
+        Eina_Bool done = EINA_FALSE;
+
+        a = strrchr(file, '/');
+        if (a)
+          b = strchr(file, '/');
+        /* messy or poorly-structured music directory; use database info
+         *
+         * this sucks due to constant round tripping, and imo it's probably
+         * worth popping an error dialog over. but empc should Just Work (tm),
+         * so I'll just soldier on here like a good little app.
+         */
+        if (a == b)
+          {
+             empd_empdd_list_info_call(empd_proxy, info_cb, file, file);
+             adds = eina_list_remove_list(adds, l);
+             return;
+          }
+
+        /* check for existing pieces of album in list */
+        a++;
+        it = eina_hash_iterator_data_new(empd_current_queue_headers);
+        EINA_ITERATOR_FOREACH(it, i)
+          {
+             const Eina_List *sub;
+             Empd_Empdd_Song *so;
+
+             item = eina_list_data_get(i);
+             so = elm_object_item_data_get(item);
+             if (!is_same_path(file, a, so->uri, NULL)) continue;
+
+             /* from the same directory: a match */
+             EINA_LIST_REVERSE_FOREACH(i, ii, item)
+               {
+                  const Eina_List *lll;
+                  Elm_Object_Item *subi;
+
+                  sub = elm_genlist_item_subitems_get(item);
+                  if (eina_list_count(sub) < 2) //just one song, ignore
+                    continue;
+                  EINA_LIST_REVERSE_FOREACH(sub, lll, subi)
+                    {
+                       Empd_Empdd_Song *ss = elm_object_item_data_get(subi);
+                       int ret;
+
+                       /* find item that goes before this one and place this 
after */
+                       ret = strcmp(ss->uri, file);
+                       if (!ret) break; //already exists here...what the 
actual fuck
+                       if (ret > 0) continue;
+                       wait_count++;
+                       empd_empdd_add_id_list_call(empd_proxy, file, 
ss->song_pos + 1);
+                       done = EINA_TRUE;
+                       break;
+                    }
+               }
+             break;
+          }
+        if (!done)
+          {
+             empd_empdd_add_list_call(empd_proxy, file);
+             wait_count++;
+          }
+        adds = eina_list_remove_list(adds, l);
+        free(file);
+        break;
+     }
+}
+
 static Eina_Bool
-db_update()
+queue_update()
+{
+   
+   if (adds && wait_count) wait_count--;
+   if (adds && (!wait_count))
+     run_adds();
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+update_timer_cb()
 {
    Eina_File *f;
    size_t size;
 
-   if (!log_dirty) return ECORE_CALLBACK_RENEW;
+   update_timer = NULL;
    f = eina_file_open(log_file, 0);
-   if (!f) return ECORE_CALLBACK_RENEW; //FIXME: probably should error or 
something?
+   if (!f) return EINA_FALSE; //FIXME: probably should error or something?
    size = eina_file_size_get(f);
    if (size > log_size)
      {
@@ -90,8 +277,6 @@ db_update()
          */
         FILE *ff;
         char txt[4096];
-        Eina_List *files = NULL;
-        char *file;
 
         ff = fopen(log_file, "rb");
         if (!fseek(ff, log_size, SEEK_SET))
@@ -99,17 +284,35 @@ db_update()
              while (fgets(txt, sizeof(txt), ff))
                {
                   char *p, *e;
+                  Eina_List **files = NULL;
                   //v
                   //Oct 09 23:55 : update: added The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
-                  p = strstr(txt, ": update: added ");
+                  //Oct 09 23:55 : update: removing The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
+                  p = strstr(txt, ": update: ");
                   if (!p) continue;
                   //             v
                   //Oct 09 23:55 : update: added The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
-                  p += sizeof(": update: added ") - 1;
-                  //                             v
-                  //Oct 09 23:55 : update: added The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
+                  //Oct 09 23:55 : update: removing The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
+                  p += sizeof(": update: ") - 1;
+                  if (!strncmp(p, "added ", sizeof("added ") - 1))
+                    {
+                       //                             v
+                       //Oct 09 23:55 : update: added The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
+                       files = &adds;
+                       p += sizeof("added ") - 1;
+                    }
+                    /*
+                  else if (!strncmp(p, "removing ", sizeof("removing ") - 1))
+                    {
+                       //                                v
+                       //Oct 09 23:55 : update: removing The 
Algorithm/Octopus4/06-Synthesiz3r.mp3\n
+                       files = &rems;
+                       p += sizeof("removing ") - 1;
+                    }
+                    */
+                  else continue;
                   e = strchr(p, '\n');
-                  files = eina_list_sorted_insert(files, 
(Eina_Compare_Cb)sort_cb, strndup(p, e - p));
+                  *files = eina_list_sorted_insert(*files, 
(Eina_Compare_Cb)sort_cb, strndup(p, e - p));
                }
           }
 #if 0 //broken because fuck you mmap
@@ -173,15 +376,24 @@ db_update()
           }
         eina_file_map_free(f, txt);
 #endif
-        EINA_LIST_FREE(files, file)
-          {
-             empd_empdd_add_list_call(empd_proxy, file);
-             free(file);
-          }
+
+         if (adds)
+           run_adds();
      }
    log_size = size;
    eina_file_close(f);
    log_dirty = EINA_FALSE;
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+db_update()
+{
+   if (!log_dirty) return ECORE_CALLBACK_RENEW;
+   if (update_timer)
+     ecore_timer_reset(update_timer);
+   else
+     update_timer = ecore_timer_add(2.0, update_timer_cb, NULL);
    return ECORE_CALLBACK_RENEW;
 }
 
@@ -261,6 +473,7 @@ auto_playlist_manager_init(void)
    E_LIST_HANDLER_APPEND(handlers, EIO_MONITOR_SELF_DELETED, log_removed, 
NULL);
    E_LIST_HANDLER_APPEND(handlers, EIO_MONITOR_SELF_RENAME, log_removed, NULL);
    E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_DATABASE_UPDATE_END_EVENT, 
db_update, NULL);
+   E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_QUEUE_LIST_EVENT, queue_update, 
NULL);
    return EINA_TRUE;
 }
 
@@ -269,6 +482,7 @@ auto_playlist_manager_shutdown(void)
 {
    E_FREE_FUNC(log_monitor, eio_monitor_del);
    E_FREE_LIST(handlers, ecore_event_handler_del);
+   E_FREE_FUNC(update_timer, ecore_timer_del);
    eina_stringshare_replace(&log_file, NULL);
    eio_shutdown();
 }

-- 


Reply via email to