diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c index ff8c281bed..73ad841c0c 100644 --- a/apps/plugins/properties.c +++ b/apps/plugins/properties.c @@ -24,6 +24,14 @@ #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) #endif +struct dir_stats { + char dirname[MAX_PATH]; + int len; + unsigned int dir_count; + unsigned int file_count; + unsigned long long byte_count; +}; + enum props_types { PROPS_FILE = 0, PROPS_ID3, @@ -34,18 +42,17 @@ static int props_type = PROPS_FILE; static struct mp3entry id3; -char str_filename[MAX_PATH]; -char str_dirname[MAX_PATH]; -char str_size[64]; -char str_dircount[64]; -char str_filecount[64]; -char str_date[64]; -char str_time[64]; +static char str_filename[MAX_PATH]; +static char str_dirname[MAX_PATH]; +static char str_size[64]; +static char str_dircount[64]; +static char str_filecount[64]; +static char str_date[64]; +static char str_time[64]; -unsigned nseconds; -unsigned long nsize; -int32_t size_unit; -struct tm tm; +static unsigned long nsize; +static int32_t size_unit; +static struct tm tm; #define NUM_FILE_PROPERTIES 5 static const unsigned char* const props_file[] = @@ -128,15 +135,7 @@ static bool file_properties(const char* selected_file) return found; } -typedef struct { - char dirname[MAX_PATH]; - int len; - unsigned int dc; - unsigned int fc; - unsigned long long bc; -} DPS; - -static bool _dir_properties(DPS *dps) +static bool _dir_properties(struct dir_stats *stats) { /* recursively scan directories in search of files and informs the user of the progress */ @@ -147,11 +146,11 @@ static bool _dir_properties(DPS *dps) struct dirent* entry; result = true; - dirlen = rb->strlen(dps->dirname); - dir = rb->opendir(dps->dirname); + dirlen = rb->strlen(stats->dirname); + dir = rb->opendir(stats->dirname); if (!dir) { - rb->splashf(HZ*2, "%s", dps->dirname); + rb->splashf(HZ*2, "%s", stats->dirname); return false; /* open error */ } @@ -160,7 +159,7 @@ static bool _dir_properties(DPS *dps) { struct dirinfo info = rb->dir_get_info(dir, entry); /* append name to current directory */ - rb->snprintf(dps->dirname+dirlen, dps->len-dirlen, "/%s", + rb->snprintf(stats->dirname+dirlen, stats->len-dirlen, "/%s", entry->d_name); if (info.attribute & ATTR_DIRECTORY) @@ -169,29 +168,30 @@ static bool _dir_properties(DPS *dps) !rb->strcmp((char *)entry->d_name, "..")) continue; /* skip these */ - dps->dc++; /* new directory */ + stats->dir_count++; /* new directory */ if (*rb->current_tick - lasttick > (HZ/8)) { unsigned log; lasttick = *rb->current_tick; rb->lcd_clear_display(); rb->lcd_puts(0,0,"SCANNING..."); - rb->lcd_puts(0,1,dps->dirname); - rb->lcd_putsf(0,2,"Directories: %d", dps->dc); - rb->lcd_putsf(0,3,"Files: %d", dps->fc); - log = human_size_log(dps->bc); - rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)), + rb->lcd_puts(0,1,stats->dirname); + rb->lcd_putsf(0,2,"Directories: %d", stats->dir_count); + rb->lcd_putsf(0,3,"Files: %d", stats->file_count); + log = human_size_log(stats->byte_count); + rb->lcd_putsf(0,4,"Size: %lu %s", + (unsigned long)(stats->byte_count >> (10*log)), rb->str(units[log])); rb->lcd_update(); } /* recursion */ - result = _dir_properties(dps); + result = _dir_properties(stats); } else { - dps->fc++; /* new file */ - dps->bc += info.size; + stats->file_count++; /* new file */ + stats->byte_count += info.size; } if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) result = false; @@ -201,17 +201,17 @@ static bool _dir_properties(DPS *dps) return result; } -static bool dir_properties(const char* selected_file, DPS *dps) +static bool dir_properties(const char* selected_file, struct dir_stats *stats) { unsigned log; - rb->strlcpy(dps->dirname, selected_file, MAX_PATH); + rb->strlcpy(stats->dirname, selected_file, MAX_PATH); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); #endif - if (!_dir_properties(dps)) + if (!_dir_properties(stats)) { #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); @@ -224,10 +224,10 @@ static bool dir_properties(const char* selected_file, DPS *dps) #endif rb->strlcpy(str_dirname, selected_file, MAX_PATH); - rb->snprintf(str_dircount, sizeof str_dircount, "%d", dps->dc); - rb->snprintf(str_filecount, sizeof str_filecount, "%d", dps->fc); - log = human_size_log(dps->bc); - nsize = (long) (dps->bc >> (log*10)); + rb->snprintf(str_dircount, sizeof str_dircount, "%d", stats->dir_count); + rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); + log = human_size_log(stats->byte_count); + nsize = (long) (stats->byte_count >> (log*10)); size_unit = units[log]; rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); return true; @@ -255,7 +255,7 @@ static const char * get_props(int selected_item, void* data, static int speak_property_selection(int selected_item, void *data) { - DPS *dps = data; + struct dir_stats *stats = data; int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]); rb->talk_id(id, false); switch (id) @@ -295,10 +295,10 @@ static int speak_property_selection(int selected_item, void *data) rb->talk_time(&tm, true); break; case LANG_PROPERTIES_SUBDIRS: - rb->talk_number(dps->dc, true); + rb->talk_number(stats->dir_count, true); break; case LANG_PROPERTIES_FILES: - rb->talk_number(dps->fc, true); + rb->talk_number(stats->file_count, true); break; default: rb->talk_spell(props_file[selected_item + 1], true); @@ -307,34 +307,49 @@ static int speak_property_selection(int selected_item, void *data) return 0; } -enum plugin_status plugin_start(const void* parameter) +static int browse_file_or_dir(struct dir_stats *stats) { struct gui_synclist properties_lists; int button; - bool quit = false, usb = false; - const char *file = parameter; - if(!parameter || (file[0] != '/')) return PLUGIN_ERROR; -#ifdef HAVE_TOUCHSCREEN - rb->touchscreen_set_mode(rb->global_settings->touch_mode); -#endif + rb->gui_synclist_init(&properties_lists, &get_props, stats, false, 2, NULL); + rb->gui_synclist_set_title(&properties_lists, + rb->str(props_type == PROPS_DIR ? + LANG_PROPERTIES_DIRECTORY_PROPERTIES : + LANG_PROPERTIES_FILE_PROPERTIES), + NOICON); + rb->gui_synclist_set_icon_callback(&properties_lists, NULL); + if (rb->global_settings->talk_menu) + rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); + rb->gui_synclist_set_nb_items(&properties_lists, + 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : + NUM_DIR_PROPERTIES)); + rb->gui_synclist_select_item(&properties_lists, 0); + rb->gui_synclist_draw(&properties_lists); + rb->gui_synclist_speak_item(&properties_lists); - static DPS dps = { - .len = MAX_PATH, - .dc = 0, - .fc = 0, - .bc = 0, - }; + while(true) + { + button = rb->get_action(CONTEXT_LIST, HZ); + /* HZ so the status bar redraws corectly */ + if (rb->gui_synclist_do_button(&properties_lists,&button)) + continue; + switch(button) + { + case ACTION_STD_CANCEL: + return false; + default: + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + return true; + break; + } + } +} - /* determine if it's a file or a directory */ - bool found = false; +static bool determine_file_or_dir(void) +{ DIR* dir; struct dirent* entry; - char* ptr = rb->strrchr(file, '/') + 1; - int dirlen = (ptr - file); - - rb->strlcpy(str_dirname, file, dirlen + 1); - rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); dir = rb->opendir(str_dirname); if (dir) @@ -345,15 +360,39 @@ enum plugin_status plugin_start(const void* parameter) { struct dirinfo info = rb->dir_get_info(dir, entry); props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE; - found = true; - break; + rb->closedir(dir); + return true; } } rb->closedir(dir); } - /* now we know if it's a file or a dir or maybe something failed */ + return false; +} - if(!found) +enum plugin_status plugin_start(const void* parameter) +{ + static struct dir_stats stats = + { + .len = MAX_PATH, + .dir_count = 0, + .file_count = 0, + .byte_count = 0, + }; + + const char *file = parameter; + if(!parameter || (file[0] != '/')) return PLUGIN_ERROR; + +#ifdef HAVE_TOUCHSCREEN + rb->touchscreen_set_mode(rb->global_settings->touch_mode); +#endif + + const char* file_name = rb->strrchr(file, '/') + 1; + int dirlen = (file_name - file); + + rb->strlcpy(str_dirname, file, dirlen + 1); + rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); + + if(!determine_file_or_dir()) { /* weird: we couldn't find the entry. This Should Never Happen (TM) */ rb->splashf(0, "File/Dir not found: %s", file); @@ -362,7 +401,7 @@ enum plugin_status plugin_start(const void* parameter) } /* get the info depending on its_a_dir */ - if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file))) + if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file))) { /* something went wrong (to do: tell user what it was (nesting,...) */ rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); @@ -373,47 +412,8 @@ enum plugin_status plugin_start(const void* parameter) FOR_NB_SCREENS(i) rb->viewportmanager_theme_enable(i, true, NULL); - if (props_type == PROPS_ID3) - usb = rb->browse_id3(&id3, 0, 0); - else - { - rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL); - rb->gui_synclist_set_title(&properties_lists, - rb->str(props_type == PROPS_DIR ? - LANG_PROPERTIES_DIRECTORY_PROPERTIES : - LANG_PROPERTIES_FILE_PROPERTIES), - NOICON); - rb->gui_synclist_set_icon_callback(&properties_lists, NULL); - if (rb->global_settings->talk_menu) - rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); - rb->gui_synclist_set_nb_items(&properties_lists, - 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : - NUM_DIR_PROPERTIES)); - rb->gui_synclist_select_item(&properties_lists, 0); - rb->gui_synclist_draw(&properties_lists); - rb->gui_synclist_speak_item(&properties_lists); - - while(!quit) - { - button = rb->get_action(CONTEXT_LIST, HZ); - /* HZ so the status bar redraws corectly */ - if (rb->gui_synclist_do_button(&properties_lists, &button)) - continue; - switch(button) - { - case ACTION_STD_CANCEL: - quit = true; - break; - default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) - { - quit = true; - usb = true; - } - break; - } - } - } + bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0) : + browse_file_or_dir(&stats); FOR_NB_SCREENS(i) rb->viewportmanager_theme_undo(i, false);