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