diff options
author | Thomas Martitz <kugel@rockbox.org> | 2012-07-18 23:36:57 +0200 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2012-07-30 21:20:51 +0200 |
commit | 63d27626e417f0e80b649ca366e79ba92473a6d4 (patch) | |
tree | b52d8bafc7d47279af5b763876121b63790324d6 | |
parent | 0a645d212c226da8f85b23125fb192fb94829628 (diff) | |
download | rockbox-63d27626e417f0e80b649ca366e79ba92473a6d4.tar.gz rockbox-63d27626e417f0e80b649ca366e79ba92473a6d4.zip |
Database: Support for multiple search roots.
Support multiple roots (i.e. scan folders) using the new folder_select()
function.
Amaximum of 12 dirs can be selected, however the setting (i.e. the entire
folder list) cannot be longer than 80 chars.
The setting works similar to the autoresume dirs: Directories are seperated
by colons, e.g. "/Music:/Podcasts". Default is "/sdcard" on android, "/" on
all other targets.
Changes are made to the multiple-root logic in tagcache.c. This is to
a) provide the logic at all on native targets and b) support more than
one root before the scan even starts (until now it was used to add roots
during scan due to symlinks).
Change-Id: I64992c0678324536e8e64cd4427c8abbd8e8b39e
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/menus/settings_menu.c | 21 | ||||
-rw-r--r-- | apps/settings.h | 1 | ||||
-rw-r--r-- | apps/settings_list.c | 8 | ||||
-rw-r--r-- | apps/tagcache.c | 93 | ||||
-rw-r--r-- | apps/tagcache.h | 2 |
6 files changed, 114 insertions, 25 deletions
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 @@ | |||
13100 | *: "Select one or more directories" | 13100 | *: "Select one or more directories" |
13101 | </voice> | 13101 | </voice> |
13102 | </phrase> | 13102 | </phrase> |
13103 | <phrase> | ||
13104 | id: LANG_SELECT_DATABASE_DIRS | ||
13105 | desc: in settings_menu | ||
13106 | user: core | ||
13107 | <source> | ||
13108 | *: "Select directories to scan" | ||
13109 | </source> | ||
13110 | <dest> | ||
13111 | *: "Select directories to scan" | ||
13112 | </dest> | ||
13113 | <voice> | ||
13114 | *: "Select directories to scan" | ||
13115 | </voice> | ||
13116 | </phrase> | ||
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) | |||
66 | splash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); | 66 | splash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); |
67 | } | 67 | } |
68 | 68 | ||
69 | static int dirs_to_scan(void) | ||
70 | { | ||
71 | if (folder_select(global_settings.tagcache_scan_paths, | ||
72 | sizeof(global_settings.tagcache_scan_paths))) | ||
73 | { | ||
74 | static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY), | ||
75 | ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; | ||
76 | static const struct text_message message = {lines, 2}; | ||
77 | |||
78 | if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) | ||
79 | tagcache_rebuild_with_splash(); | ||
80 | } | ||
81 | return 0; | ||
82 | } | ||
83 | |||
69 | #ifdef HAVE_TC_RAMCACHE | 84 | #ifdef HAVE_TC_RAMCACHE |
70 | MENUITEM_SETTING(tagcache_ram, &global_settings.tagcache_ram, NULL); | 85 | MENUITEM_SETTING(tagcache_ram, &global_settings.tagcache_ram, NULL); |
71 | #endif | 86 | #endif |
@@ -83,12 +98,16 @@ MENUITEM_FUNCTION(tc_export, 0, ID2P(LANG_TAGCACHE_EXPORT), | |||
83 | MENUITEM_FUNCTION(tc_import, 0, ID2P(LANG_TAGCACHE_IMPORT), | 98 | MENUITEM_FUNCTION(tc_import, 0, ID2P(LANG_TAGCACHE_IMPORT), |
84 | (int(*)(void))tagtree_import, NULL, | 99 | (int(*)(void))tagtree_import, NULL, |
85 | NULL, Icon_NOICON); | 100 | NULL, Icon_NOICON); |
101 | MENUITEM_FUNCTION(tc_paths, 0, ID2P(LANG_SELECT_DATABASE_DIRS), | ||
102 | dirs_to_scan, NULL, NULL, Icon_NOICON); | ||
103 | |||
86 | MAKE_MENU(tagcache_menu, ID2P(LANG_TAGCACHE), 0, Icon_NOICON, | 104 | MAKE_MENU(tagcache_menu, ID2P(LANG_TAGCACHE), 0, Icon_NOICON, |
87 | #ifdef HAVE_TC_RAMCACHE | 105 | #ifdef HAVE_TC_RAMCACHE |
88 | &tagcache_ram, | 106 | &tagcache_ram, |
89 | #endif | 107 | #endif |
90 | &tagcache_autoupdate, &tc_init, &tc_update, &runtimedb, | 108 | &tagcache_autoupdate, &tc_init, &tc_update, &runtimedb, |
91 | &tc_export, &tc_import); | 109 | &tc_export, &tc_import, &tc_paths |
110 | ); | ||
92 | #endif /* HAVE_TAGCACHE */ | 111 | #endif /* HAVE_TAGCACHE */ |
93 | /* TAGCACHE MENU */ | 112 | /* TAGCACHE MENU */ |
94 | /***********************************/ | 113 | /***********************************/ |
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 | |||
561 | 2=custom */ | 561 | 2=custom */ |
562 | unsigned char autoresume_paths[MAX_PATHNAME+1]; /* colon-separated list */ | 562 | unsigned char autoresume_paths[MAX_PATHNAME+1]; /* colon-separated list */ |
563 | bool runtimedb; /* runtime database active? */ | 563 | bool runtimedb; /* runtime database active? */ |
564 | unsigned char tagcache_scan_paths[MAX_PATHNAME+1]; | ||
564 | #endif /* HAVE_TAGCACHE */ | 565 | #endif /* HAVE_TAGCACHE */ |
565 | 566 | ||
566 | #if LCD_DEPTH > 1 | 567 | #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"; | |||
316 | 316 | ||
317 | #endif /* HAVE_RECORDING */ | 317 | #endif /* HAVE_RECORDING */ |
318 | 318 | ||
319 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | ||
320 | #define DEFAULT_TAGCACHE_SCAN_PATHS "/sdcard" | ||
321 | #else | ||
322 | #define DEFAULT_TAGCACHE_SCAN_PATHS "/" | ||
323 | #endif | ||
324 | |||
319 | #ifdef HAVE_TOUCHSCREEN | 325 | #ifdef HAVE_TOUCHSCREEN |
320 | 326 | ||
321 | static const char* list_pad_formatter(char *buffer, size_t buffer_size, | 327 | static const char* list_pad_formatter(char *buffer, size_t buffer_size, |
@@ -1355,6 +1361,8 @@ const struct settings_list settings[] = { | |||
1355 | 1361 | ||
1356 | OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false, | 1362 | OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false, |
1357 | "gather runtime data", NULL), | 1363 | "gather runtime data", NULL), |
1364 | TEXT_SETTING(0, tagcache_scan_paths, "database scan paths", | ||
1365 | DEFAULT_TAGCACHE_SCAN_PATHS, NULL, NULL), | ||
1358 | #endif | 1366 | #endif |
1359 | 1367 | ||
1360 | #if CONFIG_CODEC == SWCODEC | 1368 | #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, | |||
4272 | *unignore = file_exists(newpath); | 4272 | *unignore = file_exists(newpath); |
4273 | } | 4273 | } |
4274 | 4274 | ||
4275 | /* max roots on native. on application more can be added via malloc() */ | ||
4276 | #define MAX_STATIC_ROOTS 12 | ||
4277 | |||
4275 | static struct search_roots_ll { | 4278 | static struct search_roots_ll { |
4276 | const char *path; | 4279 | const char *path; |
4277 | struct search_roots_ll * next; | 4280 | struct search_roots_ll * next; |
4278 | } roots_ll; | 4281 | } roots_ll[MAX_STATIC_ROOTS]; |
4282 | |||
4283 | /* check if the path is already included in the search roots, by the | ||
4284 | * means that the path itself or one of its parents folders is in the list */ | ||
4285 | static bool search_root_exists(const char *path) | ||
4286 | { | ||
4287 | struct search_roots_ll *this; | ||
4288 | for(this = &roots_ll[0]; this; this = this->next) | ||
4289 | { | ||
4290 | size_t root_len = strlen(this->path); | ||
4291 | /* check if the link target is inside of an existing search root | ||
4292 | * don't add if target is inside, we'll scan it later */ | ||
4293 | if (!strncmp(this->path, path, root_len)) | ||
4294 | return true; | ||
4295 | } | ||
4296 | return false; | ||
4297 | } | ||
4279 | 4298 | ||
4280 | #ifdef APPLICATION | 4299 | #ifdef APPLICATION |
4281 | /* | 4300 | /* |
@@ -4316,14 +4335,11 @@ static bool add_search_root(const char *name) | |||
4316 | if (realpath(target, abs_target) == NULL) | 4335 | if (realpath(target, abs_target) == NULL) |
4317 | return false; | 4336 | return false; |
4318 | 4337 | ||
4319 | for(this = &roots_ll; this; prev = this, this = this->next) | 4338 | if (search_root_exists(abs_target)) |
4320 | { | 4339 | return false; |
4321 | size_t root_len = strlen(this->path); | 4340 | |
4322 | /* check if the link target is inside of an existing search root | 4341 | /* get the end of the list */ |
4323 | * don't add if target is inside, we'll scan it later */ | 4342 | for(this = &roots_ll[0]; this; prev = this, this = this->next); |
4324 | if (!strncmp(this->path, abs_target, root_len)) | ||
4325 | return false; | ||
4326 | } | ||
4327 | 4343 | ||
4328 | if (prev) | 4344 | if (prev) |
4329 | { | 4345 | { |
@@ -4347,14 +4363,22 @@ static bool add_search_root(const char *name) | |||
4347 | return false; | 4363 | return false; |
4348 | } | 4364 | } |
4349 | 4365 | ||
4366 | static int free_search_root_single(struct search_roots_ll * start) | ||
4367 | { | ||
4368 | if (start < &roots_ll[0] && start >= &roots_ll[MAX_STATIC_ROOTS]) | ||
4369 | { | ||
4370 | free(start->next); | ||
4371 | return sizeof(struct search_roots_ll); | ||
4372 | } | ||
4373 | return 0; | ||
4374 | } | ||
4375 | |||
4350 | static int free_search_roots(struct search_roots_ll * start) | 4376 | static int free_search_roots(struct search_roots_ll * start) |
4351 | { | 4377 | { |
4352 | int ret = 0; | 4378 | int ret = 0; |
4353 | if (start->next) | 4379 | if (start->next) |
4354 | { | 4380 | { |
4355 | ret += free_search_roots(start->next); | 4381 | ret += free_search_root_single(start->next); |
4356 | ret += sizeof(struct search_roots_ll); | ||
4357 | free(start->next); | ||
4358 | } | 4382 | } |
4359 | return ret; | 4383 | return ret; |
4360 | } | 4384 | } |
@@ -4459,7 +4483,8 @@ void tagcache_screensync_enable(bool state) | |||
4459 | tc_stat.syncscreen = state; | 4483 | tc_stat.syncscreen = state; |
4460 | } | 4484 | } |
4461 | 4485 | ||
4462 | void tagcache_build(const char *path) | 4486 | |
4487 | static void do_tagcache_build(const char *path[]) | ||
4463 | { | 4488 | { |
4464 | struct tagcache_header header; | 4489 | struct tagcache_header header; |
4465 | bool ret; | 4490 | bool ret; |
@@ -4501,17 +4526,29 @@ void tagcache_build(const char *path) | |||
4501 | write(cachefd, &header, sizeof(struct tagcache_header)); | 4526 | write(cachefd, &header, sizeof(struct tagcache_header)); |
4502 | 4527 | ||
4503 | ret = true; | 4528 | ret = true; |
4504 | roots_ll.path = path; | 4529 | |
4505 | roots_ll.next = NULL; | 4530 | roots_ll[0].path = path[0]; |
4531 | roots_ll[0].next = NULL; | ||
4532 | /* i is for the path vector, j for the roots_ll array | ||
4533 | * path can be skipped , but root_ll entries can't */ | ||
4534 | for(int i = 1, j = 1; path[i] && j < MAX_STATIC_ROOTS; i++) | ||
4535 | { | ||
4536 | if (search_root_exists(path[i])) /* skip this path */ | ||
4537 | continue; | ||
4538 | |||
4539 | roots_ll[j].path = path[i]; | ||
4540 | roots_ll[j-1].next = &roots_ll[j]; | ||
4541 | j++; | ||
4542 | } | ||
4543 | |||
4506 | struct search_roots_ll * this; | 4544 | struct search_roots_ll * this; |
4507 | /* check_dir might add new roots */ | 4545 | /* check_dir might add new roots */ |
4508 | for(this = &roots_ll; this; this = this->next) | 4546 | for(this = &roots_ll[0]; this; this = this->next) |
4509 | { | 4547 | { |
4510 | strcpy(curpath, this->path); | 4548 | strcpy(curpath, this->path); |
4511 | ret = ret && check_dir(this->path, true); | 4549 | ret = ret && check_dir(this->path, true); |
4512 | } | 4550 | } |
4513 | if (roots_ll.next) | 4551 | free_search_roots(&roots_ll[0]); |
4514 | free_search_roots(roots_ll.next); | ||
4515 | 4552 | ||
4516 | /* Write the header. */ | 4553 | /* Write the header. */ |
4517 | header.magic = TAGCACHE_MAGIC; | 4554 | header.magic = TAGCACHE_MAGIC; |
@@ -4558,6 +4595,18 @@ void tagcache_build(const char *path) | |||
4558 | cpu_boost(false); | 4595 | cpu_boost(false); |
4559 | } | 4596 | } |
4560 | 4597 | ||
4598 | void tagcache_build(void) | ||
4599 | { | ||
4600 | char *vect[MAX_STATIC_ROOTS + 1]; /* +1 to ensure NULL sentinel */ | ||
4601 | char str[sizeof(global_settings.tagcache_scan_paths)]; | ||
4602 | strlcpy(str, global_settings.tagcache_scan_paths, sizeof(str)); | ||
4603 | |||
4604 | int res = split_string(str, ':', vect, MAX_STATIC_ROOTS); | ||
4605 | vect[res] = NULL; | ||
4606 | |||
4607 | do_tagcache_build((const char**)vect); | ||
4608 | } | ||
4609 | |||
4561 | #ifdef HAVE_TC_RAMCACHE | 4610 | #ifdef HAVE_TC_RAMCACHE |
4562 | static void load_ramcache(void) | 4611 | static void load_ramcache(void) |
4563 | { | 4612 | { |
@@ -4643,11 +4692,11 @@ static void tagcache_thread(void) | |||
4643 | case Q_REBUILD: | 4692 | case Q_REBUILD: |
4644 | remove_files(); | 4693 | remove_files(); |
4645 | remove(TAGCACHE_FILE_TEMP); | 4694 | remove(TAGCACHE_FILE_TEMP); |
4646 | tagcache_build("/"); | 4695 | tagcache_build(); |
4647 | break; | 4696 | break; |
4648 | 4697 | ||
4649 | case Q_UPDATE: | 4698 | case Q_UPDATE: |
4650 | tagcache_build("/"); | 4699 | tagcache_build(); |
4651 | #ifdef HAVE_TC_RAMCACHE | 4700 | #ifdef HAVE_TC_RAMCACHE |
4652 | load_ramcache(); | 4701 | load_ramcache(); |
4653 | #endif | 4702 | #endif |
@@ -4665,13 +4714,13 @@ static void tagcache_thread(void) | |||
4665 | { | 4714 | { |
4666 | load_ramcache(); | 4715 | load_ramcache(); |
4667 | if (tc_stat.ramcache && global_settings.tagcache_autoupdate) | 4716 | if (tc_stat.ramcache && global_settings.tagcache_autoupdate) |
4668 | tagcache_build("/"); | 4717 | tagcache_build(); |
4669 | } | 4718 | } |
4670 | else | 4719 | else |
4671 | #endif | 4720 | #endif |
4672 | if (global_settings.tagcache_autoupdate) | 4721 | if (global_settings.tagcache_autoupdate) |
4673 | { | 4722 | { |
4674 | tagcache_build("/"); | 4723 | tagcache_build(); |
4675 | 4724 | ||
4676 | /* This will be very slow unless dircache is enabled | 4725 | /* This will be very slow unless dircache is enabled |
4677 | or target is flash based, but do it anyway for | 4726 | 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 { | |||
201 | int32_t idx_id; /* Entry number in the master index. */ | 201 | int32_t idx_id; /* Entry number in the master index. */ |
202 | }; | 202 | }; |
203 | 203 | ||
204 | void tagcache_build(const char *path); | ||
205 | |||
206 | #ifdef __PCTOOL__ | 204 | #ifdef __PCTOOL__ |
207 | void tagcache_reverse_scan(void); | 205 | void tagcache_reverse_scan(void); |
208 | #endif | 206 | #endif |