diff options
author | Christian Soffke <christian.soffke@gmail.com> | 2022-04-15 19:12:37 +0200 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2022-11-20 00:41:10 -0500 |
commit | b7603adc644a0bdf76f3045e69728ca863dc9791 (patch) | |
tree | 6bf83020b31e4912ec6602a6d88c04f42d94e01a | |
parent | da2eaf3bf78ad1e7efc900381311933eac71df2c (diff) | |
download | rockbox-b7603adc644a0bdf76f3045e69728ca863dc9791.tar.gz rockbox-b7603adc644a0bdf76f3045e69728ca863dc9791.zip |
Properties: Refactoring & Minor fix
- Extract functions for
* determining whether it's a file or dir
* showing stats for dir or file without id3
- Remove typedef for struct
- Fix unit string not being displayed correctly during scanning
(use %s instead of %cB)
Change-Id: I31440ebd96bca791a96c66511c3de9727608218a
-rw-r--r-- | apps/plugins/properties.c | 220 |
1 files changed, 110 insertions, 110 deletions
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 @@ | |||
24 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) | 24 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | struct dir_stats { | ||
28 | char dirname[MAX_PATH]; | ||
29 | int len; | ||
30 | unsigned int dir_count; | ||
31 | unsigned int file_count; | ||
32 | unsigned long long byte_count; | ||
33 | }; | ||
34 | |||
27 | enum props_types { | 35 | enum props_types { |
28 | PROPS_FILE = 0, | 36 | PROPS_FILE = 0, |
29 | PROPS_ID3, | 37 | PROPS_ID3, |
@@ -34,18 +42,17 @@ static int props_type = PROPS_FILE; | |||
34 | 42 | ||
35 | static struct mp3entry id3; | 43 | static struct mp3entry id3; |
36 | 44 | ||
37 | char str_filename[MAX_PATH]; | 45 | static char str_filename[MAX_PATH]; |
38 | char str_dirname[MAX_PATH]; | 46 | static char str_dirname[MAX_PATH]; |
39 | char str_size[64]; | 47 | static char str_size[64]; |
40 | char str_dircount[64]; | 48 | static char str_dircount[64]; |
41 | char str_filecount[64]; | 49 | static char str_filecount[64]; |
42 | char str_date[64]; | 50 | static char str_date[64]; |
43 | char str_time[64]; | 51 | static char str_time[64]; |
44 | 52 | ||
45 | unsigned nseconds; | 53 | static unsigned long nsize; |
46 | unsigned long nsize; | 54 | static int32_t size_unit; |
47 | int32_t size_unit; | 55 | static struct tm tm; |
48 | struct tm tm; | ||
49 | 56 | ||
50 | #define NUM_FILE_PROPERTIES 5 | 57 | #define NUM_FILE_PROPERTIES 5 |
51 | static const unsigned char* const props_file[] = | 58 | static const unsigned char* const props_file[] = |
@@ -128,15 +135,7 @@ static bool file_properties(const char* selected_file) | |||
128 | return found; | 135 | return found; |
129 | } | 136 | } |
130 | 137 | ||
131 | typedef struct { | 138 | static bool _dir_properties(struct dir_stats *stats) |
132 | char dirname[MAX_PATH]; | ||
133 | int len; | ||
134 | unsigned int dc; | ||
135 | unsigned int fc; | ||
136 | unsigned long long bc; | ||
137 | } DPS; | ||
138 | |||
139 | static bool _dir_properties(DPS *dps) | ||
140 | { | 139 | { |
141 | /* recursively scan directories in search of files | 140 | /* recursively scan directories in search of files |
142 | and informs the user of the progress */ | 141 | and informs the user of the progress */ |
@@ -147,11 +146,11 @@ static bool _dir_properties(DPS *dps) | |||
147 | struct dirent* entry; | 146 | struct dirent* entry; |
148 | 147 | ||
149 | result = true; | 148 | result = true; |
150 | dirlen = rb->strlen(dps->dirname); | 149 | dirlen = rb->strlen(stats->dirname); |
151 | dir = rb->opendir(dps->dirname); | 150 | dir = rb->opendir(stats->dirname); |
152 | if (!dir) | 151 | if (!dir) |
153 | { | 152 | { |
154 | rb->splashf(HZ*2, "%s", dps->dirname); | 153 | rb->splashf(HZ*2, "%s", stats->dirname); |
155 | return false; /* open error */ | 154 | return false; /* open error */ |
156 | } | 155 | } |
157 | 156 | ||
@@ -160,7 +159,7 @@ static bool _dir_properties(DPS *dps) | |||
160 | { | 159 | { |
161 | struct dirinfo info = rb->dir_get_info(dir, entry); | 160 | struct dirinfo info = rb->dir_get_info(dir, entry); |
162 | /* append name to current directory */ | 161 | /* append name to current directory */ |
163 | rb->snprintf(dps->dirname+dirlen, dps->len-dirlen, "/%s", | 162 | rb->snprintf(stats->dirname+dirlen, stats->len-dirlen, "/%s", |
164 | entry->d_name); | 163 | entry->d_name); |
165 | 164 | ||
166 | if (info.attribute & ATTR_DIRECTORY) | 165 | if (info.attribute & ATTR_DIRECTORY) |
@@ -169,29 +168,30 @@ static bool _dir_properties(DPS *dps) | |||
169 | !rb->strcmp((char *)entry->d_name, "..")) | 168 | !rb->strcmp((char *)entry->d_name, "..")) |
170 | continue; /* skip these */ | 169 | continue; /* skip these */ |
171 | 170 | ||
172 | dps->dc++; /* new directory */ | 171 | stats->dir_count++; /* new directory */ |
173 | if (*rb->current_tick - lasttick > (HZ/8)) | 172 | if (*rb->current_tick - lasttick > (HZ/8)) |
174 | { | 173 | { |
175 | unsigned log; | 174 | unsigned log; |
176 | lasttick = *rb->current_tick; | 175 | lasttick = *rb->current_tick; |
177 | rb->lcd_clear_display(); | 176 | rb->lcd_clear_display(); |
178 | rb->lcd_puts(0,0,"SCANNING..."); | 177 | rb->lcd_puts(0,0,"SCANNING..."); |
179 | rb->lcd_puts(0,1,dps->dirname); | 178 | rb->lcd_puts(0,1,stats->dirname); |
180 | rb->lcd_putsf(0,2,"Directories: %d", dps->dc); | 179 | rb->lcd_putsf(0,2,"Directories: %d", stats->dir_count); |
181 | rb->lcd_putsf(0,3,"Files: %d", dps->fc); | 180 | rb->lcd_putsf(0,3,"Files: %d", stats->file_count); |
182 | log = human_size_log(dps->bc); | 181 | log = human_size_log(stats->byte_count); |
183 | rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)), | 182 | rb->lcd_putsf(0,4,"Size: %lu %s", |
183 | (unsigned long)(stats->byte_count >> (10*log)), | ||
184 | rb->str(units[log])); | 184 | rb->str(units[log])); |
185 | rb->lcd_update(); | 185 | rb->lcd_update(); |
186 | } | 186 | } |
187 | 187 | ||
188 | /* recursion */ | 188 | /* recursion */ |
189 | result = _dir_properties(dps); | 189 | result = _dir_properties(stats); |
190 | } | 190 | } |
191 | else | 191 | else |
192 | { | 192 | { |
193 | dps->fc++; /* new file */ | 193 | stats->file_count++; /* new file */ |
194 | dps->bc += info.size; | 194 | stats->byte_count += info.size; |
195 | } | 195 | } |
196 | if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) | 196 | if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) |
197 | result = false; | 197 | result = false; |
@@ -201,17 +201,17 @@ static bool _dir_properties(DPS *dps) | |||
201 | return result; | 201 | return result; |
202 | } | 202 | } |
203 | 203 | ||
204 | static bool dir_properties(const char* selected_file, DPS *dps) | 204 | static bool dir_properties(const char* selected_file, struct dir_stats *stats) |
205 | { | 205 | { |
206 | unsigned log; | 206 | unsigned log; |
207 | 207 | ||
208 | rb->strlcpy(dps->dirname, selected_file, MAX_PATH); | 208 | rb->strlcpy(stats->dirname, selected_file, MAX_PATH); |
209 | 209 | ||
210 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 210 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
211 | rb->cpu_boost(true); | 211 | rb->cpu_boost(true); |
212 | #endif | 212 | #endif |
213 | 213 | ||
214 | if (!_dir_properties(dps)) | 214 | if (!_dir_properties(stats)) |
215 | { | 215 | { |
216 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 216 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
217 | rb->cpu_boost(false); | 217 | rb->cpu_boost(false); |
@@ -224,10 +224,10 @@ static bool dir_properties(const char* selected_file, DPS *dps) | |||
224 | #endif | 224 | #endif |
225 | 225 | ||
226 | rb->strlcpy(str_dirname, selected_file, MAX_PATH); | 226 | rb->strlcpy(str_dirname, selected_file, MAX_PATH); |
227 | rb->snprintf(str_dircount, sizeof str_dircount, "%d", dps->dc); | 227 | rb->snprintf(str_dircount, sizeof str_dircount, "%d", stats->dir_count); |
228 | rb->snprintf(str_filecount, sizeof str_filecount, "%d", dps->fc); | 228 | rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); |
229 | log = human_size_log(dps->bc); | 229 | log = human_size_log(stats->byte_count); |
230 | nsize = (long) (dps->bc >> (log*10)); | 230 | nsize = (long) (stats->byte_count >> (log*10)); |
231 | size_unit = units[log]; | 231 | size_unit = units[log]; |
232 | rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); | 232 | rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); |
233 | return true; | 233 | return true; |
@@ -255,7 +255,7 @@ static const char * get_props(int selected_item, void* data, | |||
255 | 255 | ||
256 | static int speak_property_selection(int selected_item, void *data) | 256 | static int speak_property_selection(int selected_item, void *data) |
257 | { | 257 | { |
258 | DPS *dps = data; | 258 | struct dir_stats *stats = data; |
259 | int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]); | 259 | int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]); |
260 | rb->talk_id(id, false); | 260 | rb->talk_id(id, false); |
261 | switch (id) | 261 | switch (id) |
@@ -295,10 +295,10 @@ static int speak_property_selection(int selected_item, void *data) | |||
295 | rb->talk_time(&tm, true); | 295 | rb->talk_time(&tm, true); |
296 | break; | 296 | break; |
297 | case LANG_PROPERTIES_SUBDIRS: | 297 | case LANG_PROPERTIES_SUBDIRS: |
298 | rb->talk_number(dps->dc, true); | 298 | rb->talk_number(stats->dir_count, true); |
299 | break; | 299 | break; |
300 | case LANG_PROPERTIES_FILES: | 300 | case LANG_PROPERTIES_FILES: |
301 | rb->talk_number(dps->fc, true); | 301 | rb->talk_number(stats->file_count, true); |
302 | break; | 302 | break; |
303 | default: | 303 | default: |
304 | rb->talk_spell(props_file[selected_item + 1], true); | 304 | rb->talk_spell(props_file[selected_item + 1], true); |
@@ -307,34 +307,49 @@ static int speak_property_selection(int selected_item, void *data) | |||
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | 309 | ||
310 | enum plugin_status plugin_start(const void* parameter) | 310 | static int browse_file_or_dir(struct dir_stats *stats) |
311 | { | 311 | { |
312 | struct gui_synclist properties_lists; | 312 | struct gui_synclist properties_lists; |
313 | int button; | 313 | int button; |
314 | bool quit = false, usb = false; | ||
315 | const char *file = parameter; | ||
316 | if(!parameter || (file[0] != '/')) return PLUGIN_ERROR; | ||
317 | |||
318 | #ifdef HAVE_TOUCHSCREEN | ||
319 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); | ||
320 | #endif | ||
321 | 314 | ||
322 | static DPS dps = { | 315 | rb->gui_synclist_init(&properties_lists, &get_props, stats, false, 2, NULL); |
323 | .len = MAX_PATH, | 316 | rb->gui_synclist_set_title(&properties_lists, |
324 | .dc = 0, | 317 | rb->str(props_type == PROPS_DIR ? |
325 | .fc = 0, | 318 | LANG_PROPERTIES_DIRECTORY_PROPERTIES : |
326 | .bc = 0, | 319 | LANG_PROPERTIES_FILE_PROPERTIES), |
327 | }; | 320 | NOICON); |
321 | rb->gui_synclist_set_icon_callback(&properties_lists, NULL); | ||
322 | if (rb->global_settings->talk_menu) | ||
323 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); | ||
324 | rb->gui_synclist_set_nb_items(&properties_lists, | ||
325 | 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : | ||
326 | NUM_DIR_PROPERTIES)); | ||
327 | rb->gui_synclist_select_item(&properties_lists, 0); | ||
328 | rb->gui_synclist_draw(&properties_lists); | ||
329 | rb->gui_synclist_speak_item(&properties_lists); | ||
330 | |||
331 | while(true) | ||
332 | { | ||
333 | button = rb->get_action(CONTEXT_LIST, HZ); | ||
334 | /* HZ so the status bar redraws corectly */ | ||
335 | if (rb->gui_synclist_do_button(&properties_lists,&button)) | ||
336 | continue; | ||
337 | switch(button) | ||
338 | { | ||
339 | case ACTION_STD_CANCEL: | ||
340 | return false; | ||
341 | default: | ||
342 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) | ||
343 | return true; | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
328 | 348 | ||
329 | /* determine if it's a file or a directory */ | 349 | static bool determine_file_or_dir(void) |
330 | bool found = false; | 350 | { |
331 | DIR* dir; | 351 | DIR* dir; |
332 | struct dirent* entry; | 352 | struct dirent* entry; |
333 | char* ptr = rb->strrchr(file, '/') + 1; | ||
334 | int dirlen = (ptr - file); | ||
335 | |||
336 | rb->strlcpy(str_dirname, file, dirlen + 1); | ||
337 | rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); | ||
338 | 353 | ||
339 | dir = rb->opendir(str_dirname); | 354 | dir = rb->opendir(str_dirname); |
340 | if (dir) | 355 | if (dir) |
@@ -345,15 +360,39 @@ enum plugin_status plugin_start(const void* parameter) | |||
345 | { | 360 | { |
346 | struct dirinfo info = rb->dir_get_info(dir, entry); | 361 | struct dirinfo info = rb->dir_get_info(dir, entry); |
347 | props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE; | 362 | props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE; |
348 | found = true; | 363 | rb->closedir(dir); |
349 | break; | 364 | return true; |
350 | } | 365 | } |
351 | } | 366 | } |
352 | rb->closedir(dir); | 367 | rb->closedir(dir); |
353 | } | 368 | } |
354 | /* now we know if it's a file or a dir or maybe something failed */ | 369 | return false; |
370 | } | ||
371 | |||
372 | enum plugin_status plugin_start(const void* parameter) | ||
373 | { | ||
374 | static struct dir_stats stats = | ||
375 | { | ||
376 | .len = MAX_PATH, | ||
377 | .dir_count = 0, | ||
378 | .file_count = 0, | ||
379 | .byte_count = 0, | ||
380 | }; | ||
381 | |||
382 | const char *file = parameter; | ||
383 | if(!parameter || (file[0] != '/')) return PLUGIN_ERROR; | ||
384 | |||
385 | #ifdef HAVE_TOUCHSCREEN | ||
386 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); | ||
387 | #endif | ||
388 | |||
389 | const char* file_name = rb->strrchr(file, '/') + 1; | ||
390 | int dirlen = (file_name - file); | ||
391 | |||
392 | rb->strlcpy(str_dirname, file, dirlen + 1); | ||
393 | rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); | ||
355 | 394 | ||
356 | if(!found) | 395 | if(!determine_file_or_dir()) |
357 | { | 396 | { |
358 | /* weird: we couldn't find the entry. This Should Never Happen (TM) */ | 397 | /* weird: we couldn't find the entry. This Should Never Happen (TM) */ |
359 | rb->splashf(0, "File/Dir not found: %s", file); | 398 | rb->splashf(0, "File/Dir not found: %s", file); |
@@ -362,7 +401,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
362 | } | 401 | } |
363 | 402 | ||
364 | /* get the info depending on its_a_dir */ | 403 | /* get the info depending on its_a_dir */ |
365 | if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file))) | 404 | if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file))) |
366 | { | 405 | { |
367 | /* something went wrong (to do: tell user what it was (nesting,...) */ | 406 | /* something went wrong (to do: tell user what it was (nesting,...) */ |
368 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); | 407 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); |
@@ -373,47 +412,8 @@ enum plugin_status plugin_start(const void* parameter) | |||
373 | FOR_NB_SCREENS(i) | 412 | FOR_NB_SCREENS(i) |
374 | rb->viewportmanager_theme_enable(i, true, NULL); | 413 | rb->viewportmanager_theme_enable(i, true, NULL); |
375 | 414 | ||
376 | if (props_type == PROPS_ID3) | 415 | bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0) : |
377 | usb = rb->browse_id3(&id3, 0, 0); | 416 | browse_file_or_dir(&stats); |
378 | else | ||
379 | { | ||
380 | rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL); | ||
381 | rb->gui_synclist_set_title(&properties_lists, | ||
382 | rb->str(props_type == PROPS_DIR ? | ||
383 | LANG_PROPERTIES_DIRECTORY_PROPERTIES : | ||
384 | LANG_PROPERTIES_FILE_PROPERTIES), | ||
385 | NOICON); | ||
386 | rb->gui_synclist_set_icon_callback(&properties_lists, NULL); | ||
387 | if (rb->global_settings->talk_menu) | ||
388 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); | ||
389 | rb->gui_synclist_set_nb_items(&properties_lists, | ||
390 | 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : | ||
391 | NUM_DIR_PROPERTIES)); | ||
392 | rb->gui_synclist_select_item(&properties_lists, 0); | ||
393 | rb->gui_synclist_draw(&properties_lists); | ||
394 | rb->gui_synclist_speak_item(&properties_lists); | ||
395 | |||
396 | while(!quit) | ||
397 | { | ||
398 | button = rb->get_action(CONTEXT_LIST, HZ); | ||
399 | /* HZ so the status bar redraws corectly */ | ||
400 | if (rb->gui_synclist_do_button(&properties_lists, &button)) | ||
401 | continue; | ||
402 | switch(button) | ||
403 | { | ||
404 | case ACTION_STD_CANCEL: | ||
405 | quit = true; | ||
406 | break; | ||
407 | default: | ||
408 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) | ||
409 | { | ||
410 | quit = true; | ||
411 | usb = true; | ||
412 | } | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | 417 | ||
418 | FOR_NB_SCREENS(i) | 418 | FOR_NB_SCREENS(i) |
419 | rb->viewportmanager_theme_undo(i, false); | 419 | rb->viewportmanager_theme_undo(i, false); |