diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 42acad2609..26c0051b58 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -13100,3 +13100,17 @@ *: "Select one or more directories" + + id: LANG_SELECT_DATABASE_DIRS + desc: in settings_menu + user: core + + *: "Select directories to scan" + + + *: "Select directories to scan" + + + *: "Select directories to scan" + + diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index 495040d177..f2249e3a57 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c @@ -66,6 +66,21 @@ static void tagcache_update_with_splash(void) splash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); } +static int dirs_to_scan(void) +{ + if (folder_select(global_settings.tagcache_scan_paths, + sizeof(global_settings.tagcache_scan_paths))) + { + static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY), + ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; + static const struct text_message message = {lines, 2}; + + if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) + tagcache_rebuild_with_splash(); + } + return 0; +} + #ifdef HAVE_TC_RAMCACHE MENUITEM_SETTING(tagcache_ram, &global_settings.tagcache_ram, NULL); #endif @@ -83,12 +98,16 @@ MENUITEM_FUNCTION(tc_export, 0, ID2P(LANG_TAGCACHE_EXPORT), MENUITEM_FUNCTION(tc_import, 0, ID2P(LANG_TAGCACHE_IMPORT), (int(*)(void))tagtree_import, NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(tc_paths, 0, ID2P(LANG_SELECT_DATABASE_DIRS), + dirs_to_scan, NULL, NULL, Icon_NOICON); + MAKE_MENU(tagcache_menu, ID2P(LANG_TAGCACHE), 0, Icon_NOICON, #ifdef HAVE_TC_RAMCACHE &tagcache_ram, #endif &tagcache_autoupdate, &tc_init, &tc_update, &runtimedb, - &tc_export, &tc_import); + &tc_export, &tc_import, &tc_paths + ); #endif /* HAVE_TAGCACHE */ /* TAGCACHE MENU */ /***********************************/ diff --git a/apps/settings.h b/apps/settings.h index ef0bae520e..2af29ce423 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -561,6 +561,7 @@ struct user_settings 2=custom */ unsigned char autoresume_paths[MAX_PATHNAME+1]; /* colon-separated list */ bool runtimedb; /* runtime database active? */ + unsigned char tagcache_scan_paths[MAX_PATHNAME+1]; #endif /* HAVE_TAGCACHE */ #if LCD_DEPTH > 1 diff --git a/apps/settings_list.c b/apps/settings_list.c index 5e660b4386..f27c13c4f1 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -316,6 +316,12 @@ static const char graphic_numeric[] = "graphic,numeric"; #endif /* HAVE_RECORDING */ +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) +#define DEFAULT_TAGCACHE_SCAN_PATHS "/sdcard" +#else +#define DEFAULT_TAGCACHE_SCAN_PATHS "/" +#endif + #ifdef HAVE_TOUCHSCREEN static const char* list_pad_formatter(char *buffer, size_t buffer_size, @@ -1355,6 +1361,8 @@ const struct settings_list settings[] = { OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false, "gather runtime data", NULL), + TEXT_SETTING(0, tagcache_scan_paths, "database scan paths", + DEFAULT_TAGCACHE_SCAN_PATHS, NULL, NULL), #endif #if CONFIG_CODEC == SWCODEC diff --git a/apps/tagcache.c b/apps/tagcache.c index ef642b1e3c..1f11f9e49f 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -4272,10 +4272,29 @@ static void __attribute__ ((noinline)) check_ignore(const char *dirname, *unignore = file_exists(newpath); } +/* max roots on native. on application more can be added via malloc() */ +#define MAX_STATIC_ROOTS 12 + static struct search_roots_ll { const char *path; struct search_roots_ll * next; -} roots_ll; +} roots_ll[MAX_STATIC_ROOTS]; + +/* check if the path is already included in the search roots, by the + * means that the path itself or one of its parents folders is in the list */ +static bool search_root_exists(const char *path) +{ + struct search_roots_ll *this; + for(this = &roots_ll[0]; this; this = this->next) + { + size_t root_len = strlen(this->path); + /* check if the link target is inside of an existing search root + * don't add if target is inside, we'll scan it later */ + if (!strncmp(this->path, path, root_len)) + return true; + } + return false; +} #ifdef APPLICATION /* @@ -4316,14 +4335,11 @@ static bool add_search_root(const char *name) if (realpath(target, abs_target) == NULL) return false; - for(this = &roots_ll; this; prev = this, this = this->next) - { - size_t root_len = strlen(this->path); - /* check if the link target is inside of an existing search root - * don't add if target is inside, we'll scan it later */ - if (!strncmp(this->path, abs_target, root_len)) - return false; - } + if (search_root_exists(abs_target)) + return false; + + /* get the end of the list */ + for(this = &roots_ll[0]; this; prev = this, this = this->next); if (prev) { @@ -4347,14 +4363,22 @@ static bool add_search_root(const char *name) return false; } +static int free_search_root_single(struct search_roots_ll * start) +{ + if (start < &roots_ll[0] && start >= &roots_ll[MAX_STATIC_ROOTS]) + { + free(start->next); + return sizeof(struct search_roots_ll); + } + return 0; +} + static int free_search_roots(struct search_roots_ll * start) { int ret = 0; if (start->next) { - ret += free_search_roots(start->next); - ret += sizeof(struct search_roots_ll); - free(start->next); + ret += free_search_root_single(start->next); } return ret; } @@ -4459,7 +4483,8 @@ void tagcache_screensync_enable(bool state) tc_stat.syncscreen = state; } -void tagcache_build(const char *path) + +static void do_tagcache_build(const char *path[]) { struct tagcache_header header; bool ret; @@ -4501,17 +4526,29 @@ void tagcache_build(const char *path) write(cachefd, &header, sizeof(struct tagcache_header)); ret = true; - roots_ll.path = path; - roots_ll.next = NULL; + + roots_ll[0].path = path[0]; + roots_ll[0].next = NULL; + /* i is for the path vector, j for the roots_ll array + * path can be skipped , but root_ll entries can't */ + for(int i = 1, j = 1; path[i] && j < MAX_STATIC_ROOTS; i++) + { + if (search_root_exists(path[i])) /* skip this path */ + continue; + + roots_ll[j].path = path[i]; + roots_ll[j-1].next = &roots_ll[j]; + j++; + } + struct search_roots_ll * this; /* check_dir might add new roots */ - for(this = &roots_ll; this; this = this->next) + for(this = &roots_ll[0]; this; this = this->next) { strcpy(curpath, this->path); ret = ret && check_dir(this->path, true); } - if (roots_ll.next) - free_search_roots(roots_ll.next); + free_search_roots(&roots_ll[0]); /* Write the header. */ header.magic = TAGCACHE_MAGIC; @@ -4558,6 +4595,18 @@ void tagcache_build(const char *path) cpu_boost(false); } +void tagcache_build(void) +{ + char *vect[MAX_STATIC_ROOTS + 1]; /* +1 to ensure NULL sentinel */ + char str[sizeof(global_settings.tagcache_scan_paths)]; + strlcpy(str, global_settings.tagcache_scan_paths, sizeof(str)); + + int res = split_string(str, ':', vect, MAX_STATIC_ROOTS); + vect[res] = NULL; + + do_tagcache_build((const char**)vect); +} + #ifdef HAVE_TC_RAMCACHE static void load_ramcache(void) { @@ -4643,11 +4692,11 @@ static void tagcache_thread(void) case Q_REBUILD: remove_files(); remove(TAGCACHE_FILE_TEMP); - tagcache_build("/"); + tagcache_build(); break; case Q_UPDATE: - tagcache_build("/"); + tagcache_build(); #ifdef HAVE_TC_RAMCACHE load_ramcache(); #endif @@ -4665,13 +4714,13 @@ static void tagcache_thread(void) { load_ramcache(); if (tc_stat.ramcache && global_settings.tagcache_autoupdate) - tagcache_build("/"); + tagcache_build(); } else #endif if (global_settings.tagcache_autoupdate) { - tagcache_build("/"); + tagcache_build(); /* This will be very slow unless dircache is enabled or target is flash based, but do it anyway for diff --git a/apps/tagcache.h b/apps/tagcache.h index 44161cf22c..c1d0df9bcd 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -201,8 +201,6 @@ struct tagcache_search { int32_t idx_id; /* Entry number in the master index. */ }; -void tagcache_build(const char *path); - #ifdef __PCTOOL__ void tagcache_reverse_scan(void); #endif