A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+252 -337
+183 -5
apps/plugins/lib/mul_id3.c
··· 40 40 41 41 static struct multiple_tracks_id3 mul_id3; 42 42 43 + static const int32_t units[] = 44 + { 45 + LANG_BYTE, 46 + LANG_KIBIBYTE, 47 + LANG_MEBIBYTE, 48 + LANG_GIBIBYTE 49 + }; 43 50 44 51 /* Calculate modified FNV hash of string 45 52 * has good avalanche behaviour and uniform distribution ··· 130 137 mul_id3.filesize += id3->filesize; 131 138 } 132 139 133 - /* (!) Note scale factor applied to returned metadata: 134 - * - Unit for filesize will be KiB instead of Bytes 135 - * - Unit for length will be s instead of ms 140 + /* (!) Note unit conversion below 136 141 * 137 142 * Use result only as input for browse_id3, 138 143 * with the track_ct parameter set to > 1. ··· 159 164 id3->track_string = NULL; 160 165 id3->year_string = NULL; 161 166 id3->year = mul_id3.year; 162 - mul_id3.length /= 1000; 163 - mul_id3.filesize >>= 10; 167 + mul_id3.length /= 1000; /* convert from ms to s */ 168 + mul_id3.filesize >>= 10; /* convert from B to KiB */ 164 169 id3->length = mul_id3.length > ULONG_MAX ? 0 : mul_id3.length; 165 170 id3->filesize = mul_id3.filesize > INT_MAX ? 0 : mul_id3.filesize; 166 171 id3->frequency = mul_id3.frequency; ··· 172 177 id3->track_level = 0; 173 178 id3->album_level = 0; 174 179 } 180 + 181 + unsigned long human_size(unsigned long long byte_count, int32_t *unit_lang_id) 182 + { 183 + const size_t n = sizeof(units)/sizeof(units[0]); 184 + unsigned int i; 185 + 186 + /* margin set at 10K boundary: 10239 B +1 => 10 KB */ 187 + for(i = 0; i < n-1 && byte_count >= 10*1024; i++) 188 + byte_count >>= 10; /* div by 1024 */ 189 + 190 + *unit_lang_id = units[i]; 191 + return (unsigned long)byte_count; 192 + } 193 + 194 + /* missing filetype attribute for images */ 195 + static const char *image_exts[] = {"bmp","jpg","jpe","jpeg","png","ppm"}; 196 + /* and videos */ 197 + static const char *video_exts[] = {"mpg","mpeg","mpv","m2v"}; 198 + 199 + static void prn(const char *str, int y) 200 + { 201 + rb->lcd_puts(0, y, str); 202 + #ifdef HAVE_REMOTE_LCD 203 + rb->lcd_remote_puts(0, y, str); 204 + #endif 205 + } 206 + 207 + void display_dir_stats(struct dir_stats *stats) 208 + { 209 + char buf[32]; 210 + int32_t lang_size_unit; 211 + unsigned long display_size = human_size(stats->byte_count, &lang_size_unit); 212 + rb->lcd_clear_display(); 213 + #ifdef HAVE_REMOTE_LCD 214 + rb->lcd_remote_clear_display(); 215 + #endif 216 + rb->snprintf(buf, sizeof(buf), "Files: %d (%lu %s)", stats->file_count, 217 + display_size, rb->str(lang_size_unit)); 218 + prn(buf, 0); 219 + rb->snprintf(buf, sizeof(buf), "Audio: %d", stats->audio_file_count); 220 + prn(buf, 1); 221 + if (stats->count_all) 222 + { 223 + rb->snprintf(buf, sizeof(buf), "Playlists: %d", stats->m3u_file_count); 224 + prn(buf, 2); 225 + rb->snprintf(buf, sizeof(buf), "Images: %d", stats->img_file_count); 226 + prn(buf, 3); 227 + rb->snprintf(buf, sizeof(buf), "Videos: %d", stats->vid_file_count); 228 + prn(buf, 4); 229 + rb->snprintf(buf, sizeof(buf), "Directories: %d", stats->dir_count); 230 + prn(buf, 5); 231 + rb->snprintf(buf, sizeof(buf), "Max files in Dir: %d", 232 + stats->max_files_in_dir); 233 + prn(buf, 6); 234 + } 235 + else 236 + { 237 + rb->snprintf(buf, sizeof(buf), "Directories: %d", stats->dir_count); 238 + prn(buf, 2); 239 + } 240 + rb->lcd_update(); 241 + #ifdef HAVE_REMOTE_LCD 242 + rb->lcd_remote_update(); 243 + #endif 244 + 245 + } 246 + 247 + /* Recursively scans directories in search of files 248 + * and informs the user of the progress. 249 + */ 250 + bool collect_dir_stats(struct dir_stats *stats, bool (*id3_cb)(const char*)) 251 + { 252 + bool result = true; 253 + unsigned int files_in_dir = 0; 254 + static unsigned int id3_count; 255 + static unsigned long last_displayed, last_get_action; 256 + struct dirent* entry; 257 + int dirlen = rb->strlen(stats->dirname); 258 + DIR* dir = rb->opendir(stats->dirname); 259 + if (!dir) 260 + { 261 + rb->splashf(HZ*2, "open error: %s", stats->dirname); 262 + return false; 263 + } 264 + else if (!stats->dirname[1]) /* root dir */ 265 + stats->dirname[0] = dirlen = 0; 266 + 267 + /* walk through the directory content */ 268 + while(result && (0 != (entry = rb->readdir(dir)))) 269 + { 270 + struct dirinfo info = rb->dir_get_info(dir, entry); 271 + if (info.attribute & ATTR_DIRECTORY) 272 + { 273 + if (!rb->strcmp((char *)entry->d_name, ".") || 274 + !rb->strcmp((char *)entry->d_name, "..")) 275 + continue; /* skip these */ 276 + 277 + rb->snprintf(stats->dirname + dirlen, sizeof(stats->dirname) - dirlen, 278 + "/%s", entry->d_name); /* append name to current directory */ 279 + if (!id3_cb) 280 + { 281 + stats->dir_count++; /* new directory */ 282 + if (*rb->current_tick - last_displayed > (HZ/2)) 283 + { 284 + if (last_displayed) 285 + display_dir_stats(stats); 286 + last_displayed = *(rb->current_tick); 287 + } 288 + } 289 + result = collect_dir_stats(stats, id3_cb); /* recursion */ 290 + } 291 + else if (!id3_cb) 292 + { 293 + char *ptr; 294 + stats->file_count++; /* new file */ 295 + files_in_dir++; 296 + stats->byte_count += info.size; 297 + 298 + int attr = rb->filetype_get_attr(entry->d_name); 299 + if (attr == FILE_ATTR_AUDIO) 300 + stats->audio_file_count++; 301 + else if (attr == FILE_ATTR_M3U) 302 + stats->m3u_file_count++; 303 + /* image or video file attributes have to be compared manually */ 304 + else if (stats->count_all && 305 + (ptr = rb->strrchr(entry->d_name,'.'))) 306 + { 307 + unsigned int i; 308 + ptr++; 309 + for(i = 0; i < ARRAYLEN(image_exts); i++) 310 + { 311 + if(!rb->strcasecmp(ptr, image_exts[i])) 312 + { 313 + stats->img_file_count++; 314 + break; 315 + } 316 + } 317 + if (i >= ARRAYLEN(image_exts)) { 318 + for(i = 0; i < ARRAYLEN(video_exts); i++) { 319 + if(!rb->strcasecmp(ptr, video_exts[i])) { 320 + stats->vid_file_count++; 321 + break; 322 + } 323 + } 324 + } 325 + } 326 + } 327 + else if (rb->filetype_get_attr(entry->d_name) == FILE_ATTR_AUDIO) 328 + { 329 + rb->splash_progress(id3_count++, stats->audio_file_count, 330 + "%s (%s)", 331 + rb->str(LANG_WAIT), rb->str(LANG_OFF_ABORT)); 332 + rb->snprintf(stats->dirname + dirlen, sizeof(stats->dirname) - dirlen, 333 + "/%s", entry->d_name); /* append name to current directory */ 334 + id3_cb(stats->dirname); /* allow metadata to be collected */ 335 + } 336 + 337 + if (TIME_AFTER(*(rb->current_tick), last_get_action + HZ/8)) 338 + { 339 + if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) 340 + { 341 + stats->canceled = true; 342 + result = false; 343 + } 344 + last_get_action = *(rb->current_tick); 345 + } 346 + rb->yield(); 347 + } 348 + rb->closedir(dir); 349 + if (stats->max_files_in_dir < files_in_dir) 350 + stats->max_files_in_dir = files_in_dir; 351 + return result; 352 + }
+32
apps/plugins/lib/mul_id3.h
··· 21 21 #ifndef MUL_ID3_H 22 22 #define MUL_ID3_H 23 23 24 + struct dir_stats { 25 + char dirname[MAX_PATH]; 26 + unsigned int dir_count; 27 + unsigned int file_count; 28 + unsigned int audio_file_count; 29 + unsigned int m3u_file_count; 30 + unsigned int img_file_count; 31 + unsigned int vid_file_count; 32 + unsigned int max_files_in_dir; 33 + unsigned long long byte_count; 34 + bool count_all; 35 + bool canceled; 36 + }; 37 + 38 + /* create mp3entry that contains matching metadata from multiple tracks */ 24 39 void collect_id3(struct mp3entry *id3, bool is_first_track); 25 40 void finalize_id3(struct mp3entry *id3); 41 + 42 + /* Traverse directory, collecting stats/track metadata. 43 + * 44 + * 1) If id3_cb is null, dir_properties calculates all dir stats, including the 45 + * audio file count. 46 + * 47 + * 2) If id3_cb points to a function, dir_properties will call it for every audio 48 + * file encountered, to allow the file's metadata to be collected. The displayed 49 + * progress bar's maximum value is set to the audio file count. 50 + * Stats are assumed to have already been generated by a preceding run. 51 + * 52 + * If the count_all parameter is set to false, images and videos are not counted, 53 + * nor is the playlist, image, video or max file in dir count displayed. 54 + */ 55 + bool collect_dir_stats(struct dir_stats *stats, bool (*id3_cb)(const char*)); 56 + void display_dir_stats(struct dir_stats *stats); 57 + unsigned long human_size(unsigned long long byte_count, int32_t *unit_lang_id); 26 58 27 59 #endif /* MUL_ID3_H */
+14 -141
apps/plugins/properties.c
··· 25 25 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) 26 26 #endif 27 27 28 - struct 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 - 37 28 enum props_types { 38 29 PROPS_FILE = 0, 39 30 PROPS_PLAYLIST, ··· 42 33 PROPS_DIR 43 34 }; 44 35 45 - static int props_type = PROPS_FILE; 36 + static int props_type; 46 37 47 38 static struct mp3entry id3; 48 39 static int mul_id3_count; ··· 57 48 static char str_date[64]; 58 49 static char str_time[64]; 59 50 60 - static unsigned long nsize; 61 - static int32_t size_unit; 51 + static unsigned long display_size; 52 + static int32_t lang_size_unit; 62 53 static struct tm tm; 63 54 64 55 #define NUM_FILE_PROPERTIES 5 ··· 86 77 ID2P(LANG_MENU_SHOW_ID3_INFO), str_audio_filecount, 87 78 }; 88 79 89 - static const int32_t units[] = 90 - { 91 - LANG_BYTE, 92 - LANG_KIBIBYTE, 93 - LANG_MEBIBYTE, 94 - LANG_GIBIBYTE 95 - }; 96 - 97 - static 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 - 109 80 static bool file_properties(const char* selected_file) 110 81 { 111 82 bool found = false; ··· 118 89 struct dirinfo info = rb->dir_get_info(dir, entry); 119 90 if(!rb->strcmp(entry->d_name, str_filename)) 120 91 { 121 - unsigned int log; 122 - log = human_size_log((unsigned long)info.size); 123 - nsize = ((unsigned long)info.size) >> (log*10); 124 - size_unit = units[log]; 92 + display_size = human_size(info.size, &lang_size_unit); 125 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 95 rb->gmtime_r(&info.mtime, &tm); 128 96 rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", 129 97 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); ··· 141 109 return found; 142 110 } 143 111 144 - /* Recursively scans directories in search of files 145 - * and informs the user of the progress. 146 - */ 147 - static 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 112 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 - 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 - */ 233 113 static bool dir_properties(const char* selected_file, struct dir_stats *stats, 234 114 bool (*id3_cb)(const char*)) 235 115 { 236 - unsigned int log; 237 116 bool success; 238 117 239 118 rb->strlcpy(stats->dirname, selected_file, sizeof(stats->dirname)); ··· 243 122 #ifdef HAVE_ADJUSTABLE_CPU_FREQ 244 123 rb->cpu_boost(true); 245 124 #endif 246 - success = _dir_properties(stats, id3_cb); 247 - 125 + success = collect_dir_stats(stats, id3_cb); 126 + 248 127 #ifdef HAVE_ADJUSTABLE_CPU_FREQ 249 128 rb->cpu_boost(false); 250 129 #endif ··· 259 138 rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); 260 139 rb->snprintf(str_audio_filecount, sizeof str_filecount, "%d", 261 140 stats->audio_file_count); 262 - log = human_size_log(stats->byte_count); 263 - nsize = (long) (stats->byte_count >> (log*10)); 264 - size_unit = units[log]; 265 - rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); 141 + display_size = human_size(stats->byte_count, &lang_size_unit); 142 + rb->snprintf(str_size, sizeof str_size, "%lu %s", display_size, 143 + rb->str(lang_size_unit)); 266 144 } 267 145 return true; 268 146 } ··· 320 198 rb->talk_file_or_spell(str_dirname, str_filename, NULL, true); 321 199 break; 322 200 case LANG_PROPERTIES_SIZE: 323 - rb->talk_number(nsize, true); 324 - rb->talk_id(size_unit, true); 201 + rb->talk_number(display_size, true); 202 + rb->talk_id(lang_size_unit, true); 325 203 break; 326 204 case LANG_PROPERTIES_DATE: 327 205 rb->talk_date(&tm, true); ··· 399 277 400 278 static bool determine_file_or_dir(void) 401 279 { 402 - DIR* dir; 403 280 struct dirent* entry; 404 - 405 - dir = rb->opendir(str_dirname); 281 + DIR* dir = rb->opendir(str_dirname); 406 282 if (dir) 407 283 { 408 284 while(0 != (entry = rb->readdir(dir))) ··· 482 358 { 483 359 int ret; 484 360 static struct dir_stats stats; 485 - 486 361 const char *file = parameter; 487 362 if(!parameter) 488 363 return PLUGIN_ERROR; ··· 490 365 #ifdef HAVE_TOUCHSCREEN 491 366 rb->touchscreen_set_mode(rb->global_settings->touch_mode); 492 367 #endif 493 - 494 368 if (file[0] == '/') /* single file or folder selected */ 495 369 { 496 370 const char* file_name = rb->strrchr(file, '/') + 1; 497 - int dirlen = (file_name - file); 498 - 371 + const int dirlen = (file_name - file); 499 372 rb->strlcpy(str_dirname, file, dirlen + 1); 500 373 rb->snprintf(str_filename, sizeof str_filename, "%s", file + dirlen); 501 374
+22 -185
apps/plugins/stats.c
··· 19 19 * 20 20 ****************************************************************************/ 21 21 #include "plugin.h" 22 - #include "lib/pluginlib_actions.h" 23 - 24 - 25 - static int files, dirs, audiofiles, m3ufiles, imagefiles, videofiles, largestdir; 26 - static int lasttick; 27 - static bool cancel; 28 - 29 - 30 - /* we use PLA */ 31 - #define STATS_STOP PLA_EXIT 32 - 33 - #if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 34 - || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 35 - || (CONFIG_KEYPAD == IPOD_4G_PAD) 36 - #define STATS_STOP2 PLA_UP 37 - #else 38 - #define STATS_STOP2 PLA_CANCEL 39 - #endif 40 - 41 - /* this set the context to use with PLA */ 42 - static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; 43 - 44 - /* we don't have yet a filetype attribute for image files */ 45 - static const char *image_exts[] = {"bmp","jpg","jpe","jpeg","png","ppm"}; 46 - 47 - /* neither for video ones */ 48 - static const char *video_exts[] = {"mpg","mpeg","mpv","m2v"}; 49 - 50 - static void prn(const char *str, int y) 51 - { 52 - rb->lcd_puts(0,y,str); 53 - #ifdef HAVE_REMOTE_LCD 54 - rb->lcd_remote_puts(0,y,str); 55 - #endif 56 - } 57 - 58 - static void update_screen(void) 59 - { 60 - char buf[32]; 22 + #include "lib/mul_id3.h" /* collect_dir_stats & display_dir_stats */ 61 23 62 - rb->lcd_clear_display(); 63 - #ifdef HAVE_REMOTE_LCD 64 - rb->lcd_remote_clear_display(); 24 + enum plugin_status plugin_start(const void* parameter) 25 + { 26 + (void)parameter; 27 + int button, success; 28 + static struct dir_stats stats; 29 + stats.dirname[0] = '/'; 30 + stats.count_all = true; 31 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 32 + rb->cpu_boost(true); 65 33 #endif 66 - 67 - rb->snprintf(buf, sizeof(buf), "Total Files: %d", files); 68 - prn(buf,0); 69 - rb->snprintf(buf, sizeof(buf), "Audio: %d", audiofiles); 70 - prn(buf,1); 71 - rb->snprintf(buf, sizeof(buf), "Playlists: %d", m3ufiles); 72 - prn(buf,2); 73 - rb->snprintf(buf, sizeof(buf), "Images: %d", imagefiles); 74 - prn(buf,3); 75 - rb->snprintf(buf, sizeof(buf), "Videos: %d", videofiles); 76 - prn(buf,4); 77 - rb->snprintf(buf, sizeof(buf), "Directories: %d", dirs); 78 - prn(buf,5); 79 - rb->snprintf(buf, sizeof(buf), "Max files in Dir: %d", largestdir); 80 - prn(buf,6); 81 - 82 - rb->lcd_update(); 83 - #ifdef HAVE_REMOTE_LCD 84 - rb->lcd_remote_update(); 34 + display_dir_stats(&stats); 35 + success = collect_dir_stats(&stats, NULL); 36 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 37 + rb->cpu_boost(false); 85 38 #endif 86 - } 87 - 88 - static void traversedir(char* location, char* name) 89 - { 90 - int button; 91 - struct dirent *entry; 92 - DIR* dir; 93 - char fullpath[MAX_PATH]; 94 - int files_in_dir = 0; 39 + if (!success) 40 + return PLUGIN_OK; 95 41 96 - rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name); 97 - dir = rb->opendir(fullpath); 98 - if (dir) { 99 - entry = rb->readdir(dir); 100 - while (entry) { 101 - if (cancel) 102 - break; 103 - /* Skip .. and . */ 104 - if (rb->strcmp(entry->d_name, ".") && rb->strcmp(entry->d_name, "..")) 105 - { 106 - struct dirinfo info = rb->dir_get_info(dir, entry); 107 - if (info.attribute & ATTR_DIRECTORY) { 108 - traversedir(fullpath, entry->d_name); 109 - dirs++; 110 - } 111 - else { 112 - files_in_dir++; files++; 113 - 114 - /* get the filetype from the filename */ 115 - int attr = rb->filetype_get_attr(entry->d_name); 116 - switch (attr & FILE_ATTR_MASK) 117 - { 118 - case FILE_ATTR_AUDIO: 119 - audiofiles++; 120 - break; 121 - 122 - case FILE_ATTR_M3U: 123 - m3ufiles++; 124 - break; 125 - 126 - default: 127 - { 128 - /* use hardcoded filetype_exts to count 129 - * image and video files until we get 130 - * new attributes added to filetypes.h */ 131 - char *ptr = rb->strrchr(entry->d_name,'.'); 132 - if(ptr) { 133 - unsigned i; 134 - ptr++; 135 - for(i=0;i<ARRAYLEN(image_exts);i++) { 136 - if(!rb->strcasecmp(ptr,image_exts[i])) { 137 - imagefiles++; break; 138 - } 139 - } 140 - 141 - if (i >= ARRAYLEN(image_exts)) { 142 - /* not found above - try video files */ 143 - for(i=0;i<ARRAYLEN(video_exts);i++) { 144 - if(!rb->strcasecmp(ptr,video_exts[i])) { 145 - videofiles++; break; 146 - } 147 - } 148 - } 149 - } 150 - } /* default: */ 151 - } /* switch */ 152 - } 153 - } 154 - 155 - if (*rb->current_tick - lasttick > (HZ/2)) { 156 - update_screen(); 157 - lasttick = *rb->current_tick; 158 - button = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts, 159 - ARRAYLEN(plugin_contexts)); 160 - if (button == STATS_STOP || button == STATS_STOP2) { 161 - cancel = true; 162 - break; 163 - } 164 - } 165 - 166 - entry = rb->readdir(dir); 167 - } 168 - rb->closedir(dir); 169 - } 170 - if (largestdir < files_in_dir) 171 - largestdir = files_in_dir; 172 - } 173 - 174 - /* this is the plugin entry point */ 175 - enum plugin_status plugin_start(const void* parameter) 176 - { 177 - int button; 178 - 179 - (void)parameter; 180 - 181 - files = 0; 182 - dirs = 0; 183 - audiofiles = 0; 184 - m3ufiles = 0; 185 - imagefiles = 0; 186 - videofiles = 0; 187 - largestdir = 0; 188 - cancel = false; 189 - 190 - rb->splash(HZ, "Counting..."); 191 - update_screen(); 192 - lasttick = *rb->current_tick; 193 - 194 - traversedir("", ""); 195 - if (cancel) { 196 - rb->splash(HZ, "Aborted"); 197 - return PLUGIN_OK; 198 - } 199 - update_screen(); 42 + display_dir_stats(&stats); 200 43 #ifdef HAVE_BACKLIGHT 201 44 #ifdef HAVE_REMOTE_LCD 202 45 rb->remote_backlight_on(); ··· 204 47 rb->backlight_on(); 205 48 #endif 206 49 rb->splash(HZ, "Done"); 207 - update_screen(); 50 + display_dir_stats(&stats); 208 51 while (1) { 209 - 210 - button = pluginlib_getaction(TIMEOUT_BLOCK, plugin_contexts, 211 - ARRAYLEN(plugin_contexts)); 212 - switch (button) { 213 - case STATS_STOP: 214 - case STATS_STOP2: 52 + switch (button = rb->get_action(CONTEXT_STD, TIMEOUT_BLOCK)) 53 + { 54 + case ACTION_STD_CANCEL: 215 55 return PLUGIN_OK; 216 - break; 217 56 default: 218 - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { 57 + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) 219 58 return PLUGIN_USB_CONNECTED; 220 - } 221 - break; 222 59 } 223 60 } 224 61 return PLUGIN_OK;
+1 -6
manual/plugins/stats.tex
··· 5 5 (the total number as well as the number 6 6 of audio, playlist, image and video files) 7 7 on your \dap{}. 8 - Press 9 - \nopt{IPOD_4G_PAD,IPOD_3G_PAD}{\PluginCancel{} or \PluginExit{}} 10 - \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu} 11 - to abort counting and 12 - exit the plugin. Press it again to quit after counting has 13 - finished. 8 + Press \ActionStdCancel{} to exit the plugin.