diff options
author | Teruaki Kawashima <teru@rockbox.org> | 2010-11-09 14:35:19 +0000 |
---|---|---|
committer | Teruaki Kawashima <teru@rockbox.org> | 2010-11-09 14:35:19 +0000 |
commit | 7d3f8c0921630caaaaa95edd3bd8b8d177780ebf (patch) | |
tree | eed5ac89b6ab16818f588f70802fb2b3c0f4c4cb /apps/filetypes.c | |
parent | 598f56ecb241fa65f0e13e826add006e9cc55676 (diff) | |
download | rockbox-7d3f8c0921630caaaaa95edd3bd8b8d177780ebf.tar.gz rockbox-7d3f8c0921630caaaaa95edd3bd8b8d177780ebf.zip |
Create index array to filetypes used in the open with list while loading viewers.config.
Reduced stack usage of filetype_list_viewers().
Additionally, do not allocate buffer twice for same plugin name.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28538 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/filetypes.c')
-rw-r--r-- | apps/filetypes.c | 104 |
1 files changed, 53 insertions, 51 deletions
diff --git a/apps/filetypes.c b/apps/filetypes.c index 28a2da65bb..cd4f4e79b7 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c | |||
@@ -46,8 +46,14 @@ | |||
46 | #else | 46 | #else |
47 | #define MAX_FILETYPES 128 | 47 | #define MAX_FILETYPES 128 |
48 | #endif | 48 | #endif |
49 | /* max viewer plugins */ | ||
50 | #ifdef HAVE_LCD_BITMAP | ||
51 | #define MAX_VIEWERS 56 | ||
52 | #else | ||
53 | #define MAX_VIEWERS 24 | ||
54 | #endif | ||
49 | 55 | ||
50 | /* a table for the know file types */ | 56 | /* a table for the known file types */ |
51 | static const struct filetype inbuilt_filetypes[] = { | 57 | static const struct filetype inbuilt_filetypes[] = { |
52 | { "mp3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 58 | { "mp3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
53 | { "mp2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 59 | { "mp2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
@@ -134,7 +140,7 @@ static const struct filetype inbuilt_filetypes[] = { | |||
134 | { "rsbs", FILE_ATTR_RSBS, Icon_Wps, VOICE_EXT_RSBS }, | 140 | { "rsbs", FILE_ATTR_RSBS, Icon_Wps, VOICE_EXT_RSBS }, |
135 | #if CONFIG_TUNER | 141 | #if CONFIG_TUNER |
136 | { "rfms", FILE_ATTR_RFMS, Icon_Wps, VOICE_EXT_RFMS }, | 142 | { "rfms", FILE_ATTR_RFMS, Icon_Wps, VOICE_EXT_RFMS }, |
137 | #endif | 143 | #endif |
138 | #endif | 144 | #endif |
139 | #ifdef BOOTFILE_EXT | 145 | #ifdef BOOTFILE_EXT |
140 | { BOOTFILE_EXT, FILE_ATTR_MOD, Icon_Firmware, VOICE_EXT_AJZ }, | 146 | { BOOTFILE_EXT, FILE_ATTR_MOD, Icon_Firmware, VOICE_EXT_AJZ }, |
@@ -150,7 +156,6 @@ void tree_get_filetypes(const struct filetype** types, int* count) | |||
150 | *count = sizeof(inbuilt_filetypes) / sizeof(*inbuilt_filetypes); | 156 | *count = sizeof(inbuilt_filetypes) / sizeof(*inbuilt_filetypes); |
151 | } | 157 | } |
152 | 158 | ||
153 | /* mask for dynamic filetype info in attribute */ | ||
154 | #define ROCK_EXTENSION "rock" | 159 | #define ROCK_EXTENSION "rock" |
155 | 160 | ||
156 | struct file_type { | 161 | struct file_type { |
@@ -165,8 +170,11 @@ static bool custom_icons_loaded = false; | |||
165 | #ifdef HAVE_LCD_COLOR | 170 | #ifdef HAVE_LCD_COLOR |
166 | static int custom_colors[MAX_FILETYPES+1]; | 171 | static int custom_colors[MAX_FILETYPES+1]; |
167 | #endif | 172 | #endif |
173 | /* index array to filetypes used in open with list. */ | ||
174 | static int viewers[MAX_VIEWERS]; | ||
168 | static int filetype_count = 0; | 175 | static int filetype_count = 0; |
169 | static unsigned char highest_attr = 0; | 176 | static unsigned char highest_attr = 0; |
177 | static int viewer_count = 0; | ||
170 | 178 | ||
171 | static char *filetypes_strdup(char* string) | 179 | static char *filetypes_strdup(char* string) |
172 | { | 180 | { |
@@ -174,6 +182,20 @@ static char *filetypes_strdup(char* string) | |||
174 | strcpy(buffer, string); | 182 | strcpy(buffer, string); |
175 | return buffer; | 183 | return buffer; |
176 | } | 184 | } |
185 | static char *filetypes_store_plugin(char *plugin, int n) | ||
186 | { | ||
187 | int i; | ||
188 | /* if the plugin is in the list already, use it. */ | ||
189 | for (i=0; i<viewer_count; i++) | ||
190 | { | ||
191 | if (!strcmp(filetypes[viewers[i]].plugin, plugin)) | ||
192 | return filetypes[viewers[i]].plugin; | ||
193 | } | ||
194 | /* otherwise, allocate buffer */ | ||
195 | if (viewer_count < MAX_VIEWERS) | ||
196 | viewers[viewer_count++] = n; | ||
197 | return filetypes_strdup(plugin); | ||
198 | } | ||
177 | static void read_builtin_types(void); | 199 | static void read_builtin_types(void); |
178 | static void read_config(const char* config_file); | 200 | static void read_config(const char* config_file); |
179 | #ifdef HAVE_LCD_COLOR | 201 | #ifdef HAVE_LCD_COLOR |
@@ -279,7 +301,8 @@ void filetype_init(void) | |||
279 | filetypes[0].plugin = NULL; | 301 | filetypes[0].plugin = NULL; |
280 | filetypes[0].attr = 0; | 302 | filetypes[0].attr = 0; |
281 | filetypes[0].icon = Icon_Folder; | 303 | filetypes[0].icon = Icon_Folder; |
282 | 304 | ||
305 | viewer_count = 0; | ||
283 | filetype_count = 1; | 306 | filetype_count = 1; |
284 | read_builtin_types(); | 307 | read_builtin_types(); |
285 | read_config(get_user_file_path(VIEWERS_CONFIG, IS_FILE, path, sizeof(path))); | 308 | read_config(get_user_file_path(VIEWERS_CONFIG, IS_FILE, path, sizeof(path))); |
@@ -325,14 +348,14 @@ static void read_builtin_types(void) | |||
325 | static void read_config(const char* config_file) | 348 | static void read_config(const char* config_file) |
326 | { | 349 | { |
327 | char line[64], *s, *e; | 350 | char line[64], *s, *e; |
328 | char extension[8], plugin[32]; | 351 | char *extension, *plugin; |
329 | int fd = open(config_file, O_RDONLY); | 352 | int fd = open(config_file, O_RDONLY); |
330 | if (fd < 0) | 353 | if (fd < 0) |
331 | return; | 354 | return; |
332 | /* config file is in the for | 355 | /* config file is in the format |
333 | <extension>,<plugin>,<icon code> | 356 | <extension>,<plugin>,<icon code> |
334 | ignore line if either of the first two are missing */ | 357 | ignore line if either of the first two are missing */ |
335 | while (read_line(fd, line, 64) > 0) | 358 | while (read_line(fd, line, sizeof line) > 0) |
336 | { | 359 | { |
337 | if (filetype_count >= MAX_FILETYPES) | 360 | if (filetype_count >= MAX_FILETYPES) |
338 | { | 361 | { |
@@ -346,30 +369,31 @@ static void read_config(const char* config_file) | |||
346 | if (!e) | 369 | if (!e) |
347 | continue; | 370 | continue; |
348 | *e = '\0'; | 371 | *e = '\0'; |
349 | strcpy(extension, s); | 372 | extension = s; |
350 | 373 | ||
351 | /* get the plugin */ | 374 | /* get the plugin */ |
352 | s = e+1; | 375 | s = e+1; |
353 | e = strchr(s, ','); | 376 | e = strchr(s, ','); |
354 | if (!e) | 377 | if (!e) |
355 | continue; | 378 | continue; |
356 | *e = '\0'; | 379 | *e = '\0'; |
357 | 380 | plugin = s; | |
358 | strcpy(plugin, s); | 381 | |
359 | /* ok, store this plugin/extension, check icon after */ | 382 | /* ok, store this plugin/extension, check icon after */ |
360 | filetypes[filetype_count].extension = filetypes_strdup(extension); | 383 | struct file_type *file_type = &filetypes[filetype_count]; |
361 | filetypes[filetype_count].plugin = filetypes_strdup(plugin); | 384 | file_type->extension = filetypes_strdup(extension); |
362 | filetypes[filetype_count].attr = highest_attr +1; | 385 | file_type->plugin = filetypes_store_plugin(plugin, filetype_count); |
363 | filetypes[filetype_count].icon = Icon_Questionmark; | 386 | file_type->attr = highest_attr +1; |
387 | file_type->icon = Icon_Questionmark; | ||
364 | highest_attr++; | 388 | highest_attr++; |
365 | /* get the icon */ | 389 | /* get the icon */ |
366 | s = e+1; | 390 | s = e+1; |
367 | if (*s == '*') | 391 | if (*s == '*') |
368 | filetypes[filetype_count].icon = atoi(s+1); | 392 | file_type->icon = atoi(s+1); |
369 | else if (*s == '-') | 393 | else if (*s == '-') |
370 | filetypes[filetype_count].icon = Icon_NOICON; | 394 | file_type->icon = Icon_NOICON; |
371 | else if (*s >= '0' && *s <= '9') | 395 | else if (*s >= '0' && *s <= '9') |
372 | filetypes[filetype_count].icon = Icon_Last_Themeable + atoi(s); | 396 | file_type->icon = Icon_Last_Themeable + atoi(s); |
373 | filetype_count++; | 397 | filetype_count++; |
374 | } | 398 | } |
375 | close(fd); | 399 | close(fd); |
@@ -450,45 +474,40 @@ char* filetype_get_plugin(const struct entry* file) | |||
450 | return plugin_name; | 474 | return plugin_name; |
451 | } | 475 | } |
452 | 476 | ||
453 | bool filetype_supported(int attr) | 477 | bool filetype_supported(int attr) |
454 | { | 478 | { |
455 | return find_attr(attr) >= 0; | 479 | return find_attr(attr) >= 0; |
456 | } | 480 | } |
457 | 481 | ||
458 | /**** Open With Screen ****/ | 482 | /**** Open With Screen ****/ |
459 | struct cb_data { | 483 | struct cb_data { |
460 | int *items; | ||
461 | const char *current_file; | 484 | const char *current_file; |
462 | }; | 485 | }; |
463 | 486 | ||
464 | static enum themable_icons openwith_get_icon(int selected_item, void * data) | 487 | static enum themable_icons openwith_get_icon(int selected_item, void * data) |
465 | { | 488 | { |
466 | struct cb_data *info = (struct cb_data *)data; | 489 | (void)data; |
467 | int *items = info->items; | 490 | return filetypes[viewers[selected_item]].icon; |
468 | return filetypes[items[selected_item]].icon; | ||
469 | } | 491 | } |
470 | 492 | ||
471 | static const char* openwith_get_name(int selected_item, void * data, | 493 | static const char* openwith_get_name(int selected_item, void * data, |
472 | char * buffer, size_t buffer_len) | 494 | char * buffer, size_t buffer_len) |
473 | { | 495 | { |
474 | (void)buffer; (void)buffer_len; | 496 | (void)data; (void)buffer; (void)buffer_len; |
475 | struct cb_data *info = (struct cb_data *)data; | 497 | const char *s = strrchr(filetypes[viewers[selected_item]].plugin, '/'); |
476 | int *items = info->items; | ||
477 | const char *s = strrchr(filetypes[items[selected_item]].plugin, '/'); | ||
478 | if (s) | 498 | if (s) |
479 | return s+1; | 499 | return s+1; |
480 | else return filetypes[items[selected_item]].plugin; | 500 | else return filetypes[viewers[selected_item]].plugin; |
481 | } | 501 | } |
482 | 502 | ||
483 | static int openwith_action_callback(int action, struct gui_synclist *lists) | 503 | static int openwith_action_callback(int action, struct gui_synclist *lists) |
484 | { | 504 | { |
485 | struct cb_data *info = (struct cb_data *)lists->data; | 505 | struct cb_data *info = (struct cb_data *)lists->data; |
486 | int *items = info->items; | ||
487 | int i; | 506 | int i; |
488 | if (action == ACTION_STD_OK) | 507 | if (action == ACTION_STD_OK) |
489 | { | 508 | { |
490 | char plugin[MAX_PATH]; | 509 | char plugin[MAX_PATH]; |
491 | i = items[gui_synclist_get_sel_pos(lists)]; | 510 | i = viewers[gui_synclist_get_sel_pos(lists)]; |
492 | snprintf(plugin, MAX_PATH, "%s/%s.%s", | 511 | snprintf(plugin, MAX_PATH, "%s/%s.%s", |
493 | PLUGIN_DIR, filetypes[i].plugin, ROCK_EXTENSION); | 512 | PLUGIN_DIR, filetypes[i].plugin, ROCK_EXTENSION); |
494 | plugin_load(plugin, info->current_file); | 513 | plugin_load(plugin, info->current_file); |
@@ -499,34 +518,17 @@ static int openwith_action_callback(int action, struct gui_synclist *lists) | |||
499 | 518 | ||
500 | int filetype_list_viewers(const char* current_file) | 519 | int filetype_list_viewers(const char* current_file) |
501 | { | 520 | { |
502 | int i, count = 0; | ||
503 | int items[MAX_FILETYPES]; | ||
504 | struct simplelist_info info; | 521 | struct simplelist_info info; |
505 | struct cb_data data = { items, current_file }; | 522 | struct cb_data data = { current_file }; |
506 | for (i=0; i<filetype_count && count < MAX_FILETYPES; i++) | ||
507 | { | ||
508 | if (filetypes[i].plugin) | ||
509 | { | ||
510 | int j; | ||
511 | for (j=0;j<count;j++) /* check if the plugin is in the list yet */ | ||
512 | { | ||
513 | if (!strcmp(filetypes[i].plugin,filetypes[items[j]].plugin)) | ||
514 | break; | ||
515 | } | ||
516 | if (j<count) | ||
517 | continue; /* it is so grab the next plugin */ | ||
518 | items[count++] = i; | ||
519 | } | ||
520 | } | ||
521 | #ifndef HAVE_LCD_BITMAP | 523 | #ifndef HAVE_LCD_BITMAP |
522 | if (count == 0) | 524 | if (viewer_count == 0) |
523 | { | 525 | { |
524 | /* FIX: translation! */ | 526 | /* FIX: translation! */ |
525 | splash(HZ*2, "No viewers found"); | 527 | splash(HZ*2, "No viewers found"); |
526 | return PLUGIN_OK; | 528 | return PLUGIN_OK; |
527 | } | 529 | } |
528 | #endif | 530 | #endif |
529 | simplelist_info_init(&info, str(LANG_ONPLAY_OPEN_WITH), count, &data); | 531 | simplelist_info_init(&info, str(LANG_ONPLAY_OPEN_WITH), viewer_count, &data); |
530 | info.action_callback = openwith_action_callback; | 532 | info.action_callback = openwith_action_callback; |
531 | info.get_name = openwith_get_name; | 533 | info.get_name = openwith_get_name; |
532 | info.get_icon = global_settings.show_icons?openwith_get_icon:NULL; | 534 | info.get_icon = global_settings.show_icons?openwith_get_icon:NULL; |
@@ -538,7 +540,7 @@ int filetype_load_plugin(const char* plugin, char* file) | |||
538 | int i; | 540 | int i; |
539 | char plugin_name[MAX_PATH]; | 541 | char plugin_name[MAX_PATH]; |
540 | char *s; | 542 | char *s; |
541 | 543 | ||
542 | for (i=0;i<filetype_count;i++) | 544 | for (i=0;i<filetype_count;i++) |
543 | { | 545 | { |
544 | if (filetypes[i].plugin) | 546 | if (filetypes[i].plugin) |