diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/misc.c | 23 | ||||
-rw-r--r-- | apps/misc.h | 2 | ||||
-rw-r--r-- | apps/playlist.c | 115 | ||||
-rw-r--r-- | apps/playlist.h | 3 | ||||
-rw-r--r-- | apps/plugin.c | 1 | ||||
-rw-r--r-- | apps/plugin.h | 3 | ||||
-rw-r--r-- | apps/plugins/properties.c | 107 | ||||
-rw-r--r-- | apps/tagtree.c | 24 |
8 files changed, 175 insertions, 103 deletions
diff --git a/apps/misc.c b/apps/misc.c index 7ba229a6f3..b8e69d09c6 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -200,6 +200,29 @@ bool warn_on_pl_erase(void) | |||
200 | return true; | 200 | return true; |
201 | } | 201 | } |
202 | 202 | ||
203 | bool show_search_progress(bool init, int count) | ||
204 | { | ||
205 | static int last_tick = 0; | ||
206 | |||
207 | /* Don't show splashes for 1/2 second after starting search */ | ||
208 | if (init) | ||
209 | { | ||
210 | last_tick = current_tick + HZ/2; | ||
211 | return true; | ||
212 | } | ||
213 | |||
214 | /* Update progress every 1/10 of a second */ | ||
215 | if (TIME_AFTER(current_tick, last_tick + HZ/10)) | ||
216 | { | ||
217 | splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), count, str(LANG_OFF_ABORT)); | ||
218 | if (action_userabort(TIMEOUT_NOBLOCK)) | ||
219 | return false; | ||
220 | last_tick = current_tick; | ||
221 | yield(); | ||
222 | } | ||
223 | |||
224 | return true; | ||
225 | } | ||
203 | 226 | ||
204 | /* Performance optimized version of the read_line() (see below) function. */ | 227 | /* Performance optimized version of the read_line() (see below) function. */ |
205 | int fast_readline(int fd, char *buf, int buf_size, void *parameters, | 228 | int fast_readline(int fd, char *buf, int buf_size, void *parameters, |
diff --git a/apps/misc.h b/apps/misc.h index 28a982d1da..c6485db4ff 100644 --- a/apps/misc.h +++ b/apps/misc.h | |||
@@ -110,6 +110,8 @@ void talk_timedate(void); | |||
110 | * returns true if the playlist should be replaced */ | 110 | * returns true if the playlist should be replaced */ |
111 | bool warn_on_pl_erase(void); | 111 | bool warn_on_pl_erase(void); |
112 | 112 | ||
113 | bool show_search_progress(bool init, int count); | ||
114 | |||
113 | /* Read (up to) a line of text from fd into buffer and return number of bytes | 115 | /* Read (up to) a line of text from fd into buffer and return number of bytes |
114 | * read (which may be larger than the number of bytes stored in buffer). If | 116 | * read (which may be larger than the number of bytes stored in buffer). If |
115 | * an error occurs, -1 is returned (and buffer contains whatever could be | 117 | * an error occurs, -1 is returned (and buffer contains whatever could be |
diff --git a/apps/playlist.c b/apps/playlist.c index 5a3ada8efc..3600918eb3 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -2498,75 +2498,106 @@ int playlist_insert_directory(struct playlist_info* playlist, | |||
2498 | } | 2498 | } |
2499 | 2499 | ||
2500 | /* | 2500 | /* |
2501 | * Insert all tracks from specified playlist into dynamic playlist. | 2501 | * If action_cb is *not* NULL, it will be called for every track contained |
2502 | * in the playlist specified by filename. If action_cb is NULL, you must | ||
2503 | * instead provide a playlist insert context to use for adding each track | ||
2504 | * into a dynamic playlist. | ||
2502 | */ | 2505 | */ |
2503 | int playlist_insert_playlist(struct playlist_info* playlist, const char *filename, | 2506 | bool playlist_entries_iterate(const char *filename, |
2504 | int position, bool queue) | 2507 | struct playlist_insert_context *pl_context, |
2508 | bool (*action_cb)(const char *file_name)) | ||
2505 | { | 2509 | { |
2506 | int fd = -1; | 2510 | int fd = -1, i = 0; |
2511 | bool ret = false; | ||
2507 | int max; | 2512 | int max; |
2508 | char *dir; | 2513 | char *dir; |
2509 | 2514 | ||
2510 | char temp_buf[MAX_PATH+1]; | 2515 | char temp_buf[MAX_PATH+1]; |
2511 | char trackname[MAX_PATH+1]; | 2516 | char trackname[MAX_PATH+1]; |
2512 | 2517 | ||
2513 | int result = -1; | ||
2514 | bool utf8 = is_m3u8_name(filename); | 2518 | bool utf8 = is_m3u8_name(filename); |
2515 | 2519 | ||
2516 | struct playlist_insert_context pl_context; | ||
2517 | cpu_boost(true); | 2520 | cpu_boost(true); |
2518 | 2521 | ||
2519 | if (playlist_insert_context_create(playlist, &pl_context, position, queue, true) >= 0) | 2522 | fd = open_utf8(filename, O_RDONLY); |
2523 | if (fd < 0) | ||
2520 | { | 2524 | { |
2521 | fd = open_utf8(filename, O_RDONLY); | 2525 | notify_access_error(); |
2522 | if (fd < 0) | 2526 | goto out; |
2523 | { | 2527 | } |
2524 | notify_access_error(); | ||
2525 | goto out; | ||
2526 | } | ||
2527 | 2528 | ||
2528 | /* we need the directory name for formatting purposes */ | 2529 | /* we need the directory name for formatting purposes */ |
2529 | size_t dirlen = path_dirname(filename, (const char **)&dir); | 2530 | size_t dirlen = path_dirname(filename, (const char **)&dir); |
2530 | //dir = strmemdupa(dir, dirlen); | 2531 | //dir = strmemdupa(dir, dirlen); |
2531 | 2532 | ||
2532 | while ((max = read_line(fd, temp_buf, sizeof(temp_buf))) > 0) | ||
2533 | { | ||
2534 | /* user abort */ | ||
2535 | if (action_userabort(TIMEOUT_NOBLOCK)) | ||
2536 | break; | ||
2537 | 2533 | ||
2538 | if (temp_buf[0] != '#' && temp_buf[0] != '\0') | 2534 | if (action_cb) |
2535 | show_search_progress(true, 0); | ||
2536 | |||
2537 | while ((max = read_line(fd, temp_buf, sizeof(temp_buf))) > 0) | ||
2538 | { | ||
2539 | /* user abort */ | ||
2540 | if (!action_cb && action_userabort(TIMEOUT_NOBLOCK)) | ||
2541 | break; | ||
2542 | |||
2543 | if (temp_buf[0] != '#' && temp_buf[0] != '\0') | ||
2544 | { | ||
2545 | i++; | ||
2546 | if (!utf8) | ||
2539 | { | 2547 | { |
2540 | if (!utf8) | 2548 | /* Use trackname as a temporay buffer. Note that trackname must |
2541 | { | 2549 | * be as large as temp_buf. |
2542 | /* Use trackname as a temporay buffer. Note that trackname must | 2550 | */ |
2543 | * be as large as temp_buf. | 2551 | max = convert_m3u_name(temp_buf, max, sizeof(temp_buf), trackname); |
2544 | */ | 2552 | } |
2545 | max = convert_m3u_name(temp_buf, max, sizeof(temp_buf), trackname); | ||
2546 | } | ||
2547 | 2553 | ||
2548 | /* we need to format so that relative paths are correctly | 2554 | /* we need to format so that relative paths are correctly |
2549 | handled */ | 2555 | handled */ |
2550 | if (format_track_path(trackname, temp_buf, | 2556 | if (format_track_path(trackname, temp_buf, |
2551 | sizeof(trackname), dir, dirlen) < 0) | 2557 | sizeof(trackname), dir, dirlen) < 0) |
2552 | { | 2558 | { |
2553 | goto out; | 2559 | goto out; |
2554 | } | 2560 | } |
2555 | 2561 | ||
2556 | if (playlist_insert_context_add(&pl_context, trackname) < 0) | 2562 | if (action_cb) |
2563 | { | ||
2564 | if (!action_cb(trackname)) | ||
2557 | goto out; | 2565 | goto out; |
2566 | else if (!show_search_progress(false, i)) | ||
2567 | break; | ||
2558 | } | 2568 | } |
2559 | 2569 | else if (playlist_insert_context_add(pl_context, trackname) < 0) | |
2560 | /* let the other threads work */ | 2570 | goto out; |
2561 | yield(); | ||
2562 | } | 2571 | } |
2563 | } | ||
2564 | 2572 | ||
2565 | result = 0; | 2573 | /* let the other threads work */ |
2574 | yield(); | ||
2575 | } | ||
2576 | ret = true; | ||
2566 | 2577 | ||
2567 | out: | 2578 | out: |
2568 | close(fd); | 2579 | close(fd); |
2569 | cpu_boost(false); | 2580 | cpu_boost(false); |
2581 | return ret; | ||
2582 | } | ||
2583 | |||
2584 | /* | ||
2585 | * Insert all tracks from specified playlist into dynamic playlist. | ||
2586 | */ | ||
2587 | int playlist_insert_playlist(struct playlist_info* playlist, const char *filename, | ||
2588 | int position, bool queue) | ||
2589 | { | ||
2590 | |||
2591 | int result = -1; | ||
2592 | |||
2593 | struct playlist_insert_context pl_context; | ||
2594 | cpu_boost(true); | ||
2595 | |||
2596 | if (playlist_insert_context_create(playlist, &pl_context, position, queue, true) >= 0 | ||
2597 | && playlist_entries_iterate(filename, &pl_context, NULL)) | ||
2598 | result = 0; | ||
2599 | |||
2600 | cpu_boost(false); | ||
2570 | playlist_insert_context_release(&pl_context); | 2601 | playlist_insert_context_release(&pl_context); |
2571 | return result; | 2602 | return result; |
2572 | } | 2603 | } |
diff --git a/apps/playlist.h b/apps/playlist.h index 4d814c7523..f7426df9a3 100644 --- a/apps/playlist.h +++ b/apps/playlist.h | |||
@@ -159,6 +159,9 @@ int playlist_insert_directory(struct playlist_info* playlist, | |||
159 | bool recurse); | 159 | bool recurse); |
160 | int playlist_insert_playlist(struct playlist_info* playlist, const char *filename, | 160 | int playlist_insert_playlist(struct playlist_info* playlist, const char *filename, |
161 | int position, bool queue); | 161 | int position, bool queue); |
162 | bool playlist_entries_iterate(const char *filename, | ||
163 | struct playlist_insert_context *pl_context, | ||
164 | bool (*action_cb)(const char *file_name)); | ||
162 | void playlist_skip_entry(struct playlist_info *playlist, int steps); | 165 | void playlist_skip_entry(struct playlist_info *playlist, int steps); |
163 | int playlist_delete(struct playlist_info* playlist, int index); | 166 | int playlist_delete(struct playlist_info* playlist, int index); |
164 | int playlist_move(struct playlist_info* playlist, int index, int new_index); | 167 | int playlist_move(struct playlist_info* playlist, int index, int new_index); |
diff --git a/apps/plugin.c b/apps/plugin.c index 931b8f1fd4..7934cc1754 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -838,6 +838,7 @@ static const struct plugin_api rockbox_api = { | |||
838 | playlist_get_first_index, | 838 | playlist_get_first_index, |
839 | playlist_get_display_index, | 839 | playlist_get_display_index, |
840 | filetype_get_plugin, | 840 | filetype_get_plugin, |
841 | playlist_entries_iterate, | ||
841 | }; | 842 | }; |
842 | 843 | ||
843 | static int plugin_buffer_handle; | 844 | static int plugin_buffer_handle; |
diff --git a/apps/plugin.h b/apps/plugin.h index df519f28cf..e9dedf02a1 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -975,6 +975,9 @@ struct plugin_api { | |||
975 | int (*playlist_get_first_index)(const struct playlist_info* playlist); | 975 | int (*playlist_get_first_index)(const struct playlist_info* playlist); |
976 | int (*playlist_get_display_index)(void); | 976 | int (*playlist_get_display_index)(void); |
977 | char* (*filetype_get_plugin)(int attr, char *buffer, size_t buffer_len); | 977 | char* (*filetype_get_plugin)(int attr, char *buffer, size_t buffer_len); |
978 | bool (*playlist_entries_iterate)(const char *filename, | ||
979 | struct playlist_insert_context *pl_context, | ||
980 | bool (*action_cb)(const char *file_name)); | ||
978 | }; | 981 | }; |
979 | 982 | ||
980 | /* plugin header */ | 983 | /* plugin header */ |
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c index ce3c03694c..32bc8b9150 100644 --- a/apps/plugins/properties.c +++ b/apps/plugins/properties.c | |||
@@ -19,10 +19,7 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "plugin.h" | 21 | #include "plugin.h" |
22 | |||
23 | #ifdef HAVE_TAGCACHE | ||
24 | #include "lib/mul_id3.h" | 22 | #include "lib/mul_id3.h" |
25 | #endif | ||
26 | 23 | ||
27 | #if !defined(ARRAY_SIZE) | 24 | #if !defined(ARRAY_SIZE) |
28 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) | 25 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) |
@@ -38,6 +35,7 @@ struct dir_stats { | |||
38 | 35 | ||
39 | enum props_types { | 36 | enum props_types { |
40 | PROPS_FILE = 0, | 37 | PROPS_FILE = 0, |
38 | PROPS_PLAYLIST, | ||
41 | PROPS_ID3, | 39 | PROPS_ID3, |
42 | PROPS_MUL_ID3, | 40 | PROPS_MUL_ID3, |
43 | PROPS_DIR | 41 | PROPS_DIR |
@@ -46,10 +44,8 @@ enum props_types { | |||
46 | static int props_type = PROPS_FILE; | 44 | static int props_type = PROPS_FILE; |
47 | 45 | ||
48 | static struct mp3entry id3; | 46 | static struct mp3entry id3; |
49 | #ifdef HAVE_TAGCACHE | ||
50 | static int mul_id3_count; | 47 | static int mul_id3_count; |
51 | static int skipped_count; | 48 | static int skipped_count; |
52 | #endif | ||
53 | 49 | ||
54 | static char str_filename[MAX_PATH]; | 50 | static char str_filename[MAX_PATH]; |
55 | static char str_dirname[MAX_PATH]; | 51 | static char str_dirname[MAX_PATH]; |
@@ -64,6 +60,7 @@ static int32_t size_unit; | |||
64 | static struct tm tm; | 60 | static struct tm tm; |
65 | 61 | ||
66 | #define NUM_FILE_PROPERTIES 5 | 62 | #define NUM_FILE_PROPERTIES 5 |
63 | #define NUM_PLAYLIST_PROPERTIES 1 + NUM_FILE_PROPERTIES | ||
67 | static const unsigned char* const props_file[] = | 64 | static const unsigned char* const props_file[] = |
68 | { | 65 | { |
69 | ID2P(LANG_PROPERTIES_PATH), str_dirname, | 66 | ID2P(LANG_PROPERTIES_PATH), str_dirname, |
@@ -71,6 +68,7 @@ static const unsigned char* const props_file[] = | |||
71 | ID2P(LANG_PROPERTIES_SIZE), str_size, | 68 | ID2P(LANG_PROPERTIES_SIZE), str_size, |
72 | ID2P(LANG_PROPERTIES_DATE), str_date, | 69 | ID2P(LANG_PROPERTIES_DATE), str_date, |
73 | ID2P(LANG_PROPERTIES_TIME), str_time, | 70 | ID2P(LANG_PROPERTIES_TIME), str_time, |
71 | ID2P(LANG_MENU_SHOW_ID3_INFO), "...", | ||
74 | }; | 72 | }; |
75 | 73 | ||
76 | #define NUM_DIR_PROPERTIES 4 | 74 | #define NUM_DIR_PROPERTIES 4 |
@@ -120,7 +118,8 @@ static bool file_properties(const char* selected_file) | |||
120 | log = human_size_log((unsigned long)info.size); | 118 | log = human_size_log((unsigned long)info.size); |
121 | nsize = ((unsigned long)info.size) >> (log*10); | 119 | nsize = ((unsigned long)info.size) >> (log*10); |
122 | size_unit = units[log]; | 120 | size_unit = units[log]; |
123 | rb->snprintf(str_size, sizeof str_size, "%lu %s", nsize, rb->str(size_unit)); | 121 | rb->snprintf(str_size, sizeof str_size, "%lu %s", |
122 | nsize, rb->str(size_unit)); | ||
124 | rb->gmtime_r(&info.mtime, &tm); | 123 | rb->gmtime_r(&info.mtime, &tm); |
125 | rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", | 124 | rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", |
126 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | 125 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); |
@@ -249,7 +248,7 @@ static const char * get_props(int selected_item, void* data, | |||
249 | if (PROPS_DIR == props_type) | 248 | if (PROPS_DIR == props_type) |
250 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" : | 249 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" : |
251 | (char *) p2str(props_dir[selected_item]), buffer_len); | 250 | (char *) p2str(props_dir[selected_item]), buffer_len); |
252 | else if (PROPS_FILE == props_type) | 251 | else |
253 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" : | 252 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" : |
254 | (char *) p2str(props_file[selected_item]), buffer_len); | 253 | (char *) p2str(props_file[selected_item]), buffer_len); |
255 | 254 | ||
@@ -259,7 +258,8 @@ static const char * get_props(int selected_item, void* data, | |||
259 | static int speak_property_selection(int selected_item, void *data) | 258 | static int speak_property_selection(int selected_item, void *data) |
260 | { | 259 | { |
261 | struct dir_stats *stats = data; | 260 | struct dir_stats *stats = data; |
262 | int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]); | 261 | int32_t id = P2ID((props_type == PROPS_DIR ? |
262 | props_dir : props_file)[selected_item]); | ||
263 | rb->talk_id(id, false); | 263 | rb->talk_id(id, false); |
264 | switch (id) | 264 | switch (id) |
265 | { | 265 | { |
@@ -326,7 +326,8 @@ static int browse_file_or_dir(struct dir_stats *stats) | |||
326 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); | 326 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); |
327 | rb->gui_synclist_set_nb_items(&properties_lists, | 327 | rb->gui_synclist_set_nb_items(&properties_lists, |
328 | 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : | 328 | 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : |
329 | NUM_DIR_PROPERTIES)); | 329 | props_type == PROPS_PLAYLIST ? |
330 | NUM_PLAYLIST_PROPERTIES : NUM_DIR_PROPERTIES)); | ||
330 | rb->gui_synclist_select_item(&properties_lists, 0); | 331 | rb->gui_synclist_select_item(&properties_lists, 0); |
331 | rb->gui_synclist_draw(&properties_lists); | 332 | rb->gui_synclist_draw(&properties_lists); |
332 | rb->gui_synclist_speak_item(&properties_lists); | 333 | rb->gui_synclist_speak_item(&properties_lists); |
@@ -339,11 +340,17 @@ static int browse_file_or_dir(struct dir_stats *stats) | |||
339 | continue; | 340 | continue; |
340 | switch(button) | 341 | switch(button) |
341 | { | 342 | { |
343 | case ACTION_STD_OK: | ||
344 | if (props_type == PROPS_PLAYLIST && | ||
345 | rb->gui_synclist_get_sel_pos(&properties_lists) | ||
346 | == ARRAY_SIZE(props_file) - 2) | ||
347 | return -1; | ||
348 | break; | ||
342 | case ACTION_STD_CANCEL: | 349 | case ACTION_STD_CANCEL: |
343 | return false; | 350 | return 0; |
344 | default: | 351 | default: |
345 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) | 352 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) |
346 | return true; | 353 | return 1; |
347 | break; | 354 | break; |
348 | } | 355 | } |
349 | } | 356 | } |
@@ -372,7 +379,6 @@ static bool determine_file_or_dir(void) | |||
372 | return false; | 379 | return false; |
373 | } | 380 | } |
374 | 381 | ||
375 | #ifdef HAVE_TAGCACHE | ||
376 | bool mul_id3_add(const char *file_name) | 382 | bool mul_id3_add(const char *file_name) |
377 | { | 383 | { |
378 | if (!file_name || rb->mp3info(&id3, file_name)) | 384 | if (!file_name || rb->mp3info(&id3, file_name)) |
@@ -385,10 +391,37 @@ bool mul_id3_add(const char *file_name) | |||
385 | 391 | ||
386 | return true; | 392 | return true; |
387 | } | 393 | } |
394 | |||
395 | static bool has_pl_extension(const char* filename) | ||
396 | { | ||
397 | char *dot = rb->strrchr(filename, '.'); | ||
398 | return (dot && (!rb->strcasecmp(dot, ".m3u") || !rb->strcasecmp(dot, ".m3u8"))); | ||
399 | } | ||
400 | |||
401 | /* Assemble track info from a database table or the contents of a playlist file */ | ||
402 | static bool assemble_track_info(const char *filename) | ||
403 | { | ||
404 | props_type = PROPS_MUL_ID3; | ||
405 | mul_id3_count = skipped_count = 0; | ||
406 | |||
407 | if ( (filename && !rb->playlist_entries_iterate(filename, NULL, &mul_id3_add)) | ||
408 | #ifdef HAVE_TAGCACHE | ||
409 | || (!filename && !rb->tagtree_subentries_do_action(&mul_id3_add)) | ||
388 | #endif | 410 | #endif |
411 | || mul_id3_count == 0) | ||
412 | return false; | ||
413 | else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ | ||
414 | finalize_id3(&id3); | ||
415 | |||
416 | if (skipped_count > 0) | ||
417 | rb->splashf(HZ*2, "Skipped %d", skipped_count); | ||
418 | |||
419 | return true; | ||
420 | } | ||
389 | 421 | ||
390 | enum plugin_status plugin_start(const void* parameter) | 422 | enum plugin_status plugin_start(const void* parameter) |
391 | { | 423 | { |
424 | int ret; | ||
392 | static struct dir_stats stats = | 425 | static struct dir_stats stats = |
393 | { | 426 | { |
394 | .len = MAX_PATH, | 427 | .len = MAX_PATH, |
@@ -405,23 +438,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
405 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); | 438 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); |
406 | #endif | 439 | #endif |
407 | 440 | ||
408 | #ifdef HAVE_TAGCACHE | 441 | if (file[0] == '/') /* single file selected */ |
409 | if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) /* db table selected */ | ||
410 | { | ||
411 | props_type = PROPS_MUL_ID3; | ||
412 | mul_id3_count = skipped_count = 0; | ||
413 | |||
414 | if (!rb->tagtree_subentries_do_action(&mul_id3_add) || mul_id3_count == 0) | ||
415 | return PLUGIN_ERROR; | ||
416 | else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ | ||
417 | finalize_id3(&id3); | ||
418 | |||
419 | if (skipped_count > 0) | ||
420 | rb->splashf(HZ*2, "Skipped %d", skipped_count); | ||
421 | } | ||
422 | else | ||
423 | #endif | ||
424 | if (file[0] == '/') /* single track selected */ | ||
425 | { | 442 | { |
426 | const char* file_name = rb->strrchr(file, '/') + 1; | 443 | const char* file_name = rb->strrchr(file, '/') + 1; |
427 | int dirlen = (file_name - file); | 444 | int dirlen = (file_name - file); |
@@ -437,8 +454,12 @@ enum plugin_status plugin_start(const void* parameter) | |||
437 | return PLUGIN_OK; | 454 | return PLUGIN_OK; |
438 | } | 455 | } |
439 | 456 | ||
457 | if (props_type == PROPS_FILE && has_pl_extension(file)) | ||
458 | props_type = PROPS_PLAYLIST; | ||
459 | |||
440 | /* get the info depending on its_a_dir */ | 460 | /* get the info depending on its_a_dir */ |
441 | if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file))) | 461 | if(!(props_type == PROPS_DIR ? |
462 | dir_properties(file, &stats) : file_properties(file))) | ||
442 | { | 463 | { |
443 | /* something went wrong (to do: tell user what it was (nesting,...) */ | 464 | /* something went wrong (to do: tell user what it was (nesting,...) */ |
444 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); | 465 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); |
@@ -446,20 +467,32 @@ enum plugin_status plugin_start(const void* parameter) | |||
446 | return PLUGIN_OK; | 467 | return PLUGIN_OK; |
447 | } | 468 | } |
448 | } | 469 | } |
449 | else | 470 | /* database table selected */ |
471 | else if (rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER)) | ||
472 | || !assemble_track_info(NULL)) | ||
450 | return PLUGIN_ERROR; | 473 | return PLUGIN_ERROR; |
451 | 474 | ||
452 | FOR_NB_SCREENS(i) | 475 | FOR_NB_SCREENS(i) |
453 | rb->viewportmanager_theme_enable(i, true, NULL); | 476 | rb->viewportmanager_theme_enable(i, true, NULL); |
454 | 477 | ||
455 | bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm, 1) : | 478 | if (props_type == PROPS_ID3) |
456 | #ifdef HAVE_TAGCACHE | 479 | ret = rb->browse_id3(&id3, 0, 0, &tm, 1); /* Track Info for single file */ |
457 | props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : | 480 | else if (props_type == PROPS_MUL_ID3) |
458 | #endif | 481 | ret = rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count); /* database tracks */ |
459 | browse_file_or_dir(&stats); | 482 | else if ((ret = browse_file_or_dir(&stats)) < 0) |
483 | ret = assemble_track_info(file) ? /* playlist tracks */ | ||
484 | rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : -1; | ||
460 | 485 | ||
461 | FOR_NB_SCREENS(i) | 486 | FOR_NB_SCREENS(i) |
462 | rb->viewportmanager_theme_undo(i, false); | 487 | rb->viewportmanager_theme_undo(i, false); |
463 | 488 | ||
464 | return usb ? PLUGIN_USB_CONNECTED : PLUGIN_OK; | 489 | switch (ret) |
490 | { | ||
491 | case 1: | ||
492 | return PLUGIN_USB_CONNECTED; | ||
493 | case -1: | ||
494 | return PLUGIN_ERROR; | ||
495 | default: | ||
496 | return PLUGIN_OK; | ||
497 | } | ||
465 | } | 498 | } |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 3a875d6da6..be728dcc95 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -1312,30 +1312,6 @@ void tagtree_init(void) | |||
1312 | initialize_tagtree(); | 1312 | initialize_tagtree(); |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | static bool show_search_progress(bool init, int count) | ||
1316 | { | ||
1317 | static int last_tick = 0; | ||
1318 | |||
1319 | /* Don't show splashes for 1/2 second after starting search */ | ||
1320 | if (init) | ||
1321 | { | ||
1322 | last_tick = current_tick + HZ/2; | ||
1323 | return true; | ||
1324 | } | ||
1325 | |||
1326 | /* Update progress every 1/10 of a second */ | ||
1327 | if (TIME_AFTER(current_tick, last_tick + HZ/10)) | ||
1328 | { | ||
1329 | splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), count, str(LANG_OFF_ABORT)); | ||
1330 | if (action_userabort(TIMEOUT_NOBLOCK)) | ||
1331 | return false; | ||
1332 | last_tick = current_tick; | ||
1333 | yield(); | ||
1334 | } | ||
1335 | |||
1336 | return true; | ||
1337 | } | ||
1338 | |||
1339 | static int format_str(struct tagcache_search *tcs, struct display_format *fmt, | 1315 | static int format_str(struct tagcache_search *tcs, struct display_format *fmt, |
1340 | char *buf, int buf_size) | 1316 | char *buf, int buf_size) |
1341 | { | 1317 | { |