1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 Henrik Backe
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
32 #include "filetypes.h"
40 /* max plugin name size without extensions and path */
41 #define MAX_PLUGIN_LENGTH 32
43 /* max filetypes (plugins & icons stored here) */
44 #if CONFIG_CODEC == SWCODEC
45 #define MAX_FILETYPES 64
47 #define MAX_FILETYPES 48
50 /* max exttypes (extensions stored here) */
51 #if CONFIG_CODEC == SWCODEC
52 /* Software codecs require more file extensions */
53 #define MAX_EXTTYPES 64
55 #define MAX_EXTTYPES 32
58 /* string buffer length */
59 #define STRING_BUFFER_SIZE 548
61 /* number of bytes for the binary icon */
64 /* mask for dynamic filetype info in attribute */
65 #define FILETYPES_MASK 0xFF00
68 #define ROCK_EXTENSION ".rock"
69 #define VIEWERS_CONFIG ROCKBOX_DIR "/viewers.config"
70 #define VIEWERS_DIR ROCKBOX_DIR "/viewers"
72 /* global variables */
73 static int cnt_filetypes
;
74 static int cnt_exttypes
;
75 static struct ext_type exttypes
[MAX_EXTTYPES
];
76 static struct file_type filetypes
[MAX_FILETYPES
];
77 static int first_soft_exttype
;
78 static int first_soft_filetype
;
79 static char* next_free_string
;
80 static char plugin_name
[sizeof(VIEWERS_DIR
) + 7 + MAX_PLUGIN_LENGTH
];
81 static char string_buffer
[STRING_BUFFER_SIZE
];
84 #ifdef HAVE_LCD_BITMAP
85 static char* string2icon(const char*);
86 static int add_plugin(char*,char*);
88 static int add_plugin(char*);
90 static char* get_string(const char*);
91 static int find_attr_index(int);
92 static bool read_config(const char*);
93 static void rm_whitespaces(char*);
94 static void scan_plugins(void);
96 /* initialize dynamic filetypes (called at boot from tree.c) */
97 void filetype_init(void)
100 const struct filetype
* ftypes
;
102 memset(exttypes
,0,sizeof(exttypes
));
103 memset(filetypes
,0,sizeof(filetypes
));
104 next_free_string
=string_buffer
;
106 /* The special filetype folder must always be stored at index 0 */
107 #ifdef HAVE_LCD_BITMAP
108 if (!filetypes
[0].icon
)
109 filetypes
[0].icon
= bitmap_icons_6x8
[Icon_Folder
];
111 if (!filetypes
[0].icon
)
112 filetypes
[0].icon
= Icon_Folder
;
113 for (i
=1; i
< MAX_FILETYPES
; i
++)
114 filetypes
[i
].icon
= -1;
117 /* register hardcoded filetypes */
118 tree_get_filetypes(&ftypes
, &cnt
);
122 for (i
= 0; i
< cnt
; i
++)
124 ix
= ((ftypes
[i
].tree_attr
& FILETYPES_MASK
) >> 8);
125 if (ix
< MAX_FILETYPES
&& i
< MAX_EXTTYPES
)
127 #ifdef HAVE_LCD_BITMAP
128 if (filetypes
[ix
].icon
== NULL
)
129 filetypes
[ix
].icon
=bitmap_icons_6x8
[ftypes
[i
].icon
];
131 if (filetypes
[ix
].icon
== -1)
132 filetypes
[ix
].icon
=ftypes
[i
].icon
;
134 if (ix
> cnt_filetypes
)
136 exttypes
[cnt_exttypes
].type
=&filetypes
[ix
];
137 exttypes
[cnt_exttypes
].extension
=ftypes
[i
].extension
;
141 first_soft_exttype
=cnt_exttypes
;
143 first_soft_filetype
=cnt_filetypes
;
145 /* register dynamic filetypes */
146 read_config(VIEWERS_CONFIG
);
151 #ifdef HAVE_LCD_BITMAP
152 const unsigned char* filetype_get_icon(int attr
)
154 int filetype_get_icon(int attr
)
159 ix
= find_attr_index(attr
);
163 #ifdef HAVE_LCD_BITMAP
171 return filetypes
[ix
].icon
;
176 char* filetype_get_plugin(const struct entry
* file
)
180 ix
=find_attr_index(file
->attr
);
187 if ((filetypes
[ix
].plugin
== NULL
) ||
188 (strlen(filetypes
[ix
].plugin
) > MAX_PLUGIN_LENGTH
))
191 snprintf(plugin_name
, sizeof(plugin_name
),
192 "%s/%s.rock", ROCKBOX_DIR
, filetypes
[ix
].plugin
);
197 /* check if filetype is supported */
198 bool filetype_supported(int attr
)
202 ix
=find_attr_index(attr
);
204 /* hard filetypes and soft filetypes with plugins is supported */
206 if (filetypes
[ix
].plugin
|| ix
< first_soft_filetype
)
212 /* get the "dynamic" attribute for an extension */
213 int filetype_get_attr(const char* name
)
216 const char *cp
= strrchr(name
,'.');
218 if (!cp
) /* no extension? -> can't be a supported type */
222 for (i
=0; i
< cnt_exttypes
; i
++)
224 if (exttypes
[i
].extension
)
226 if (!strcasecmp(cp
,exttypes
[i
].extension
))
228 return ((((unsigned long)exttypes
[i
].type
-
229 (unsigned long)&filetypes
[0]) /
230 sizeof(struct file_type
)) << 8);
238 /* fill a menu list with viewers (used in onplay.c) */
239 int filetype_load_menu(struct menu_item
* menu
,int max_items
)
245 for (i
=0; i
< cnt_filetypes
; i
++)
247 if (filetypes
[i
].plugin
)
250 for (j
=0;j
<cnt
;j
++) /* check if the plugin is in the list yet */
252 if (!strcmp(menu
[j
].desc
,filetypes
[i
].plugin
))
255 if (j
<cnt
) continue; /* it is so grab the next plugin */
256 cp
=strrchr(filetypes
[i
].plugin
,'/');
258 else cp
=filetypes
[i
].plugin
;
259 menu
[cnt
].desc
= (unsigned char *)cp
;
261 if (cnt
== max_items
)
268 /* start a plugin with an argument (called from onplay.c) */
269 int filetype_load_plugin(const char* plugin
, char* file
)
272 snprintf(plugin_name
,sizeof(plugin_name
),"%s/%s.rock",
274 if ((fd
= open(plugin_name
,O_RDONLY
))>=0)
277 return plugin_load(plugin_name
,file
);
281 snprintf(plugin_name
,sizeof(plugin_name
),"%s/%s.rock",
283 if ((fd
= open(plugin_name
,O_RDONLY
))>=0)
286 return plugin_load(plugin_name
,file
);
292 /* get index to filetypes[] from the file attribute */
293 static int find_attr_index(int attr
)
296 ix
= ((attr
& FILETYPES_MASK
) >> 8);
298 if ((attr
& ATTR_DIRECTORY
)==ATTR_DIRECTORY
)
306 if (ix
> cnt_filetypes
)
309 if ((filetypes
[ix
].plugin
== NULL
) &&
310 #ifdef HAVE_LCD_BITMAP
311 (filetypes
[ix
].icon
== NULL
)
313 (filetypes
[ix
].icon
== -1)
322 /* scan the plugin directory and register filetypes */
323 static void scan_plugins(void)
326 struct dirent
*entry
;
334 dir
= opendir(VIEWERS_DIR
);
340 /* exttypes[] full, bail out */
341 if (cnt_exttypes
>= MAX_EXTTYPES
)
343 gui_syncsplash(HZ
, str(LANG_FILETYPES_EXTENSION_FULL
));
347 /* filetypes[] full, bail out */
348 if (cnt_filetypes
>= MAX_FILETYPES
)
350 gui_syncsplash(HZ
, str(LANG_FILETYPES_FULL
));
354 entry
= readdir(dir
);
359 /* skip directories */
360 if ((entry
->attribute
& ATTR_DIRECTORY
))
363 /* Skip FAT volume ID */
364 if (entry
->attribute
& ATTR_VOLUME_ID
)
367 /* filter out dotfiles and hidden files */
368 if ((entry
->d_name
[0]=='.') ||
369 (entry
->attribute
& ATTR_HIDDEN
)) {
373 /* filter out non rock files */
374 if (strcasecmp((char *)&entry
->d_name
[strlen((char *)entry
->d_name
) -
375 sizeof(ROCK_EXTENSION
) + 1],
380 /* filter out to long filenames */
381 if (strlen((char *)entry
->d_name
) > MAX_PLUGIN_LENGTH
+ 5)
383 gui_syncsplash(HZ
, str(LANG_FILETYPES_PLUGIN_NAME_LONG
));
387 dot
=strrchr((char *)entry
->d_name
,'.');
389 dash
=strchr((char *)entry
->d_name
,'-');
391 /* add plugin and extension */
395 ix
=(filetype_get_attr((char *)entry
->d_name
) >> 8);
398 cp
=get_string((char *)entry
->d_name
);
401 exttypes
[cnt_exttypes
].extension
=cp
;
402 exttypes
[cnt_exttypes
].type
=&filetypes
[cnt_filetypes
];
403 #ifdef HAVE_LCD_BITMAP
404 exttypes
[cnt_exttypes
].type
->icon
= bitmap_icons_6x8
[Icon_Plugin
];
406 exttypes
[cnt_exttypes
].type
->icon
= Icon_Plugin
;
411 cp
=get_string((char *)entry
->d_name
);
414 filetypes
[cnt_filetypes
].plugin
=cp
;
426 if (!filetypes
[ix
].plugin
)
428 cp
=get_string((char *)entry
->d_name
);
431 filetypes
[cnt_filetypes
].plugin
=cp
;
440 /* add plugin only */
444 for (i
= first_soft_filetype
; i
< cnt_filetypes
; i
++)
446 if (filetypes
[i
].plugin
)
447 if (!strcasecmp(filetypes
[i
].plugin
, (char *)entry
->d_name
))
456 cp
=get_string((char *)entry
->d_name
);
459 filetypes
[cnt_filetypes
].plugin
=cp
;
460 filetypes
[cnt_filetypes
].no_extension
=true;
472 #ifdef HAVE_LCD_BITMAP
473 static int add_plugin(char *plugin
, char *icon
)
475 static int add_plugin(char *plugin
)
485 /* starting now, Oct 2005, the plugins are given without extension in the
486 viewers.config file */
487 cp
=strrchr(plugin
, '.');
492 for (i
=first_soft_filetype
; i
< cnt_filetypes
; i
++)
494 if (filetypes
[i
].plugin
)
496 if (!strcasecmp(plugin
, filetypes
[i
].plugin
))
498 #ifdef HAVE_LCD_BITMAP
499 if (filetypes
[i
].icon
== NULL
&& icon
)
501 cp
= string2icon(icon
);
503 filetypes
[cnt_filetypes
].icon
= (unsigned char *)cp
;
514 cp
= get_string(plugin
);
517 filetypes
[cnt_filetypes
].plugin
= cp
;
518 #ifdef HAVE_LCD_BITMAP
522 cp
= string2icon(icon
);
524 filetypes
[cnt_filetypes
].icon
= (unsigned char *)cp
;
536 return cnt_filetypes
- 1;
539 /* read config file (or cahe file) */
540 static bool read_config(const char* file
)
544 #ifdef HAVE_LCD_BITMAP
556 fd
= open(file
, O_RDONLY
);
560 while (read_line(fd
, buf
, sizeof(buf
)))
562 if (cnt_exttypes
>= MAX_EXTTYPES
)
564 gui_syncsplash(HZ
, str(LANG_FILETYPES_EXTENSION_FULL
));
568 if (cnt_filetypes
>= MAX_FILETYPES
)
570 gui_syncsplash(HZ
, str(LANG_FILETYPES_FULL
));
577 if (strlen(buf
) == 0)
583 memset(str
,0,sizeof(str
));
590 str
[i
] = strtok_r(cp
, ",", &end
);
593 while (end
&& i
< last
)
603 str
[i
] = strtok_r(NULL
, ",", &end
);
610 /* bail out if no icon and no plugin */
612 #ifdef HAVE_LCD_BITMAP
618 /* bail out if no plugin and icon is incorrect*/
620 #ifdef HAVE_LCD_BITMAP
621 && strlen(str
[icon
]) != ICON_LENGTH
*2
626 /* bail out if no icon and no plugin and no extension*/
628 #ifdef HAVE_LCD_BITMAP
634 /* bail out if we are not able to start plugin from onplay.c ?*/
637 if (strlen(str
[plugin
]) > MAX_PLUGIN_LENGTH
)
639 gui_syncsplash(HZ
, str(LANG_FILETYPES_PLUGIN_NAME_LONG
));
646 /* if extension already exist don't add a new one */
647 for (i
=0; i
< cnt_exttypes
; i
++)
649 if (!strcasecmp(str
[extension
],exttypes
[i
].extension
))
651 #ifdef HAVE_LCD_BITMAP
652 ix
=add_plugin(str
[plugin
],NULL
);
655 if (str
[icon
] && filetypes
[ix
].icon
== NULL
)
657 if (exttypes
[i
].type
->icon
== NULL
)
659 cp
= string2icon(str
[icon
]);
661 exttypes
[i
].type
->icon
= (unsigned char *)cp
;
666 ix
=add_plugin(str
[plugin
]);
668 if (exttypes
[i
].type
== NULL
)
670 exttypes
[i
].type
= &filetypes
[ix
];
681 #ifdef HAVE_LCD_BITMAP
682 ix
=add_plugin(str
[plugin
],str
[icon
]);
684 ix
=add_plugin(str
[plugin
]);
688 cp
=get_string(str
[extension
]);
691 exttypes
[cnt_exttypes
].extension
= cp
;
693 exttypes
[cnt_exttypes
].type
= &filetypes
[ix
];
695 filetypes
[i
].no_extension
=false;
709 #ifdef HAVE_LCD_BITMAP
710 ix
=add_plugin(str
[plugin
],str
[icon
]);
712 ix
=add_plugin(str
[plugin
]);
714 filetypes
[ix
].no_extension
=true;
724 #ifdef HAVE_LCD_BITMAP
725 /* convert an ascii hexadecimal icon to a binary icon */
726 static char* string2icon(const char* str
)
728 char tmp
[ICON_LENGTH
*2];
732 if (strlen(str
)!=ICON_LENGTH
*2)
735 if ((sizeof(string_buffer
) +
736 (unsigned long) string_buffer
-
737 (unsigned long) next_free_string
) < ICON_LENGTH
)
739 gui_syncsplash(HZ
, str(LANG_FILETYPES_STRING_BUFFER_EMPTY
));
745 if (str
[i
] >= '0' && str
[i
] <= '9')
751 if (str
[i
] >= 'a' && str
[i
] <= 'f')
753 tmp
[i
]=str
[i
]-'a'+10;
757 if (str
[i
] >= 'A' && str
[i
] <= 'F')
759 tmp
[i
]=str
[i
]-'A'+10;
767 for (i
= 0; i
< ICON_LENGTH
; i
++)
768 cp
[i
]=((tmp
[i
*2]<<4) | tmp
[i
*2+1]);
770 next_free_string
=&next_free_string
[ICON_LENGTH
];
775 /* get string from buffer */
776 static char* get_string(const char* str
)
778 unsigned int l
=strlen(str
)+1;
784 if (l
<= (sizeof(string_buffer
) +
785 (unsigned long) string_buffer
-
786 (unsigned long) next_free_string
))
788 strcpy(next_free_string
, str
);
790 next_free_string
=&next_free_string
[l
];
795 gui_syncsplash(HZ
, str(LANG_FILETYPES_STRING_BUFFER_EMPTY
));
800 /* remove all white spaces from string */
801 static void rm_whitespaces(char* str
)
808 while (cp
< &str
[strlen(str
)])