summaryrefslogtreecommitdiff
path: root/apps/plugins/properties.c
diff options
context:
space:
mode:
authorChristian Soffke <christian.soffke@gmail.com>2024-07-25 20:49:20 +0200
committerChristian Soffke <christian.soffke@gmail.com>2024-07-28 20:18:41 +0200
commit545271c4de82c3b5da05ca91629d0de150c90d21 (patch)
tree51b579da8c05bdabeb64c426f883e1dca2f89782 /apps/plugins/properties.c
parent6d19214eeb13835f3343675417651e2eb03e270f (diff)
downloadrockbox-545271c4de82c3b5da05ca91629d0de150c90d21.tar.gz
rockbox-545271c4de82c3b5da05ca91629d0de150c90d21.zip
plugins: extract redundant functionality from stats/properties
Also: - Enables cpu boosting for Stats (*much* faster on some players) - Displays file size in Stats Change-Id: I888ba054e1f8c2985fbf8dca36e11e6ef130e7ca
Diffstat (limited to 'apps/plugins/properties.c')
-rw-r--r--apps/plugins/properties.c155
1 files changed, 14 insertions, 141 deletions
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index 1156bd5ca9..c932474f8c 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -25,15 +25,6 @@
25 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) 25 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
26#endif 26#endif
27 27
28struct dir_stats {
29 char dirname[MAX_PATH];
30 unsigned int dir_count;
31 unsigned int file_count;
32 unsigned int audio_file_count;
33 unsigned long long byte_count;
34 bool canceled;
35};
36
37enum props_types { 28enum props_types {
38 PROPS_FILE = 0, 29 PROPS_FILE = 0,
39 PROPS_PLAYLIST, 30 PROPS_PLAYLIST,
@@ -42,7 +33,7 @@ enum props_types {
42 PROPS_DIR 33 PROPS_DIR
43}; 34};
44 35
45static int props_type = PROPS_FILE; 36static int props_type;
46 37
47static struct mp3entry id3; 38static struct mp3entry id3;
48static int mul_id3_count; 39static int mul_id3_count;
@@ -57,8 +48,8 @@ static char str_audio_filecount[64];
57static char str_date[64]; 48static char str_date[64];
58static char str_time[64]; 49static char str_time[64];
59 50
60static unsigned long nsize; 51static unsigned long display_size;
61static int32_t size_unit; 52static int32_t lang_size_unit;
62static struct tm tm; 53static struct tm tm;
63 54
64#define NUM_FILE_PROPERTIES 5 55#define NUM_FILE_PROPERTIES 5
@@ -86,26 +77,6 @@ static const unsigned char* const props_dir[] =
86 ID2P(LANG_MENU_SHOW_ID3_INFO), str_audio_filecount, 77 ID2P(LANG_MENU_SHOW_ID3_INFO), str_audio_filecount,
87}; 78};
88 79
89static const int32_t units[] =
90{
91 LANG_BYTE,
92 LANG_KIBIBYTE,
93 LANG_MEBIBYTE,
94 LANG_GIBIBYTE
95};
96
97static unsigned int human_size_log(unsigned long long size)
98{
99 const size_t n = sizeof(units)/sizeof(units[0]);
100
101 unsigned int i;
102 /* margin set at 10K boundary: 10239 B +1 => 10 KB */
103 for(i=0; i < n-1 && size >= 10*1024; i++)
104 size >>= 10; /* div by 1024 */
105
106 return i;
107}
108
109static bool file_properties(const char* selected_file) 80static bool file_properties(const char* selected_file)
110{ 81{
111 bool found = false; 82 bool found = false;
@@ -118,12 +89,9 @@ static bool file_properties(const char* selected_file)
118 struct dirinfo info = rb->dir_get_info(dir, entry); 89 struct dirinfo info = rb->dir_get_info(dir, entry);
119 if(!rb->strcmp(entry->d_name, str_filename)) 90 if(!rb->strcmp(entry->d_name, str_filename))
120 { 91 {
121 unsigned int log; 92 display_size = human_size(info.size, &lang_size_unit);
122 log = human_size_log((unsigned long)info.size);
123 nsize = ((unsigned long)info.size) >> (log*10);
124 size_unit = units[log];
125 rb->snprintf(str_size, sizeof str_size, "%lu %s", 93 rb->snprintf(str_size, sizeof str_size, "%lu %s",
126 nsize, rb->str(size_unit)); 94 display_size, rb->str(lang_size_unit));
127 rb->gmtime_r(&info.mtime, &tm); 95 rb->gmtime_r(&info.mtime, &tm);
128 rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", 96 rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d",
129 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 97 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
@@ -141,99 +109,10 @@ static bool file_properties(const char* selected_file)
141 return found; 109 return found;
142} 110}
143 111
144/* Recursively scans directories in search of files
145 * and informs the user of the progress.
146 */
147static bool _dir_properties(struct dir_stats *stats, bool (*id3_cb)(const char*))
148{
149 bool result = true;
150 static unsigned long last_lcd_update, last_get_action;
151 struct dirent* entry;
152 int dirlen = rb->strlen(stats->dirname);
153 DIR* dir = rb->opendir(stats->dirname);
154 if (!dir)
155 {
156 rb->splashf(HZ*2, "open error: %s", stats->dirname);
157 return false;
158 }
159
160 /* walk through the directory content */
161 while(result && (0 != (entry = rb->readdir(dir))))
162 {
163 struct dirinfo info = rb->dir_get_info(dir, entry);
164 if (info.attribute & ATTR_DIRECTORY)
165 {
166 if (!rb->strcmp((char *)entry->d_name, ".") ||
167 !rb->strcmp((char *)entry->d_name, ".."))
168 continue; /* skip these */
169
170 rb->snprintf(stats->dirname + dirlen, sizeof(stats->dirname) - dirlen,
171 "/%s", entry->d_name); /* append name to current directory */
172
173 if (!id3_cb)
174 {
175 stats->dir_count++; /* new directory */
176 if (*rb->current_tick - last_lcd_update > (HZ/2))
177 {
178 unsigned int log;
179 last_lcd_update = *(rb->current_tick);
180 rb->lcd_clear_display();
181 rb->lcd_putsf(0, 0, "Directories: %d", stats->dir_count);
182 rb->lcd_putsf(0, 1, "Files: %d (Audio: %d)",
183 stats->file_count, stats->audio_file_count);
184 log = human_size_log(stats->byte_count);
185 rb->lcd_putsf(0, 2, "Size: %lu %s",
186 (unsigned long)(stats->byte_count >> (10*log)),
187 rb->str(units[log]));
188 rb->lcd_update();
189 }
190 }
191
192 result = _dir_properties(stats, id3_cb); /* recursion */
193 }
194 else if (!id3_cb)
195 {
196 stats->file_count++; /* new file */
197 stats->byte_count += info.size;
198 if (rb->filetype_get_attr(entry->d_name) == FILE_ATTR_AUDIO)
199 stats->audio_file_count++;
200 }
201 else if (rb->filetype_get_attr(entry->d_name) == FILE_ATTR_AUDIO)
202 {
203 rb->splash_progress(mul_id3_count, stats->audio_file_count, "%s (%s)",
204 rb->str(LANG_WAIT), rb->str(LANG_OFF_ABORT));
205 rb->snprintf(stats->dirname + dirlen, sizeof(stats->dirname) - dirlen,
206 "/%s", entry->d_name); /* append name to current directory */
207 id3_cb(stats->dirname); /* allow metadata to be collected */
208 }
209 112
210 if (TIME_AFTER(*(rb->current_tick), last_get_action + HZ/8))
211 {
212 if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK))
213 {
214 stats->canceled = true;
215 result = false;
216 }
217 last_get_action = *(rb->current_tick);
218 }
219 rb->yield();
220 }
221 rb->closedir(dir);
222 return result;
223}
224
225/* 1) If id3_cb is null, dir_properties calculates all dir stats, including the
226 * audio file count.
227 *
228 * 2) If id3_cb points to a function, dir_properties will call it for every audio
229 * file encountered, to allow the file's metadata to be collected. The displayed
230 * progress bar's maximum value is set to the audio file count.
231 * Stats are assumed to have already been generated by a preceding run.
232 */
233static bool dir_properties(const char* selected_file, struct dir_stats *stats, 113static bool dir_properties(const char* selected_file, struct dir_stats *stats,
234 bool (*id3_cb)(const char*)) 114 bool (*id3_cb)(const char*))
235{ 115{
236 unsigned int log;
237 bool success; 116 bool success;
238 117
239 rb->strlcpy(stats->dirname, selected_file, sizeof(stats->dirname)); 118 rb->strlcpy(stats->dirname, selected_file, sizeof(stats->dirname));
@@ -243,8 +122,8 @@ static bool dir_properties(const char* selected_file, struct dir_stats *stats,
243#ifdef HAVE_ADJUSTABLE_CPU_FREQ 122#ifdef HAVE_ADJUSTABLE_CPU_FREQ
244 rb->cpu_boost(true); 123 rb->cpu_boost(true);
245#endif 124#endif
246 success = _dir_properties(stats, id3_cb); 125 success = collect_dir_stats(stats, id3_cb);
247 126
248#ifdef HAVE_ADJUSTABLE_CPU_FREQ 127#ifdef HAVE_ADJUSTABLE_CPU_FREQ
249 rb->cpu_boost(false); 128 rb->cpu_boost(false);
250#endif 129#endif
@@ -259,10 +138,9 @@ static bool dir_properties(const char* selected_file, struct dir_stats *stats,
259 rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); 138 rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count);
260 rb->snprintf(str_audio_filecount, sizeof str_filecount, "%d", 139 rb->snprintf(str_audio_filecount, sizeof str_filecount, "%d",
261 stats->audio_file_count); 140 stats->audio_file_count);
262 log = human_size_log(stats->byte_count); 141 display_size = human_size(stats->byte_count, &lang_size_unit);
263 nsize = (long) (stats->byte_count >> (log*10)); 142 rb->snprintf(str_size, sizeof str_size, "%lu %s", display_size,
264 size_unit = units[log]; 143 rb->str(lang_size_unit));
265 rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit));
266 } 144 }
267 return true; 145 return true;
268} 146}
@@ -320,8 +198,8 @@ static int speak_property_selection(int selected_item, void *data)
320 rb->talk_file_or_spell(str_dirname, str_filename, NULL, true); 198 rb->talk_file_or_spell(str_dirname, str_filename, NULL, true);
321 break; 199 break;
322 case LANG_PROPERTIES_SIZE: 200 case LANG_PROPERTIES_SIZE:
323 rb->talk_number(nsize, true); 201 rb->talk_number(display_size, true);
324 rb->talk_id(size_unit, true); 202 rb->talk_id(lang_size_unit, true);
325 break; 203 break;
326 case LANG_PROPERTIES_DATE: 204 case LANG_PROPERTIES_DATE:
327 rb->talk_date(&tm, true); 205 rb->talk_date(&tm, true);
@@ -399,10 +277,8 @@ static int browse_file_or_dir(struct dir_stats *stats)
399 277
400static bool determine_file_or_dir(void) 278static bool determine_file_or_dir(void)
401{ 279{
402 DIR* dir;
403 struct dirent* entry; 280 struct dirent* entry;
404 281 DIR* dir = rb->opendir(str_dirname);
405 dir = rb->opendir(str_dirname);
406 if (dir) 282 if (dir)
407 { 283 {
408 while(0 != (entry = rb->readdir(dir))) 284 while(0 != (entry = rb->readdir(dir)))
@@ -482,7 +358,6 @@ enum plugin_status plugin_start(const void* parameter)
482{ 358{
483 int ret; 359 int ret;
484 static struct dir_stats stats; 360 static struct dir_stats stats;
485
486 const char *file = parameter; 361 const char *file = parameter;
487 if(!parameter) 362 if(!parameter)
488 return PLUGIN_ERROR; 363 return PLUGIN_ERROR;
@@ -490,12 +365,10 @@ enum plugin_status plugin_start(const void* parameter)
490#ifdef HAVE_TOUCHSCREEN 365#ifdef HAVE_TOUCHSCREEN
491 rb->touchscreen_set_mode(rb->global_settings->touch_mode); 366 rb->touchscreen_set_mode(rb->global_settings->touch_mode);
492#endif 367#endif
493
494 if (file[0] == '/') /* single file or folder selected */ 368 if (file[0] == '/') /* single file or folder selected */
495 { 369 {
496 const char* file_name = rb->strrchr(file, '/') + 1; 370 const char* file_name = rb->strrchr(file, '/') + 1;
497 int dirlen = (file_name - file); 371 const int dirlen = (file_name - file);
498
499 rb->strlcpy(str_dirname, file, dirlen + 1); 372 rb->strlcpy(str_dirname, file, dirlen + 1);
500 rb->snprintf(str_filename, sizeof str_filename, "%s", file + dirlen); 373 rb->snprintf(str_filename, sizeof str_filename, "%s", file + dirlen);
501 374