diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2007-03-29 06:16:00 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2007-03-29 06:16:00 +0000 |
commit | 21165a3f3db3c777f8522b14f16e570107b0405b (patch) | |
tree | a3e2766c1424ded8a2de37ba28f0a709ee3d4ded /apps/filetypes.c | |
parent | d71b531c25ad0e02f4124e6e8cb851f59e4bbc65 (diff) | |
download | rockbox-21165a3f3db3c777f8522b14f16e570107b0405b.tar.gz rockbox-21165a3f3db3c777f8522b14f16e570107b0405b.zip |
Recode filetypes.c to remove its need for a static string buffer.
Functional changes:
- filetypes.c handles the open with menu now instead of onplay.c
- automatic plugin registration no longer works (did anyone know about you could do this?)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12959 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/filetypes.c')
-rw-r--r-- | apps/filetypes.c | 905 |
1 files changed, 212 insertions, 693 deletions
diff --git a/apps/filetypes.c b/apps/filetypes.c index 49ce1c72aa..d374b559ce 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2004 Henrik Backe | 10 | * Copyright (C) 2007 Jonathan Gordon |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 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. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -21,6 +21,8 @@ | |||
21 | #include <string.h> | 21 | #include <string.h> |
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include <stdbool.h> | 23 | #include <stdbool.h> |
24 | #include "string.h" | ||
25 | #include <ctype.h> | ||
24 | 26 | ||
25 | #include "sprintf.h" | 27 | #include "sprintf.h" |
26 | #include "settings.h" | 28 | #include "settings.h" |
@@ -36,791 +38,308 @@ | |||
36 | #include "file.h" | 38 | #include "file.h" |
37 | #include "icons.h" | 39 | #include "icons.h" |
38 | #include "splash.h" | 40 | #include "splash.h" |
39 | 41 | #include "buffer.h" | |
40 | /* max plugin name size without extensions and path */ | ||
41 | #define MAX_PLUGIN_LENGTH 32 | ||
42 | 42 | ||
43 | /* max filetypes (plugins & icons stored here) */ | 43 | /* max filetypes (plugins & icons stored here) */ |
44 | #if CONFIG_CODEC == SWCODEC | 44 | #if CONFIG_CODEC == SWCODEC |
45 | #define MAX_FILETYPES 64 | 45 | #define MAX_FILETYPES 72 |
46 | #else | 46 | #else |
47 | #define MAX_FILETYPES 48 | 47 | #define MAX_FILETYPES 48 |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | /* max exttypes (extensions stored here) */ | ||
51 | #if CONFIG_CODEC == SWCODEC | ||
52 | /* Software codecs require more file extensions */ | ||
53 | #define MAX_EXTTYPES 64 | ||
54 | #else | ||
55 | #define MAX_EXTTYPES 32 | ||
56 | #endif | ||
57 | |||
58 | /* string buffer length */ | ||
59 | #define STRING_BUFFER_SIZE 548 | ||
60 | |||
61 | /* number of bytes for the binary icon */ | 50 | /* number of bytes for the binary icon */ |
62 | #define ICON_LENGTH 6 | 51 | #define ICON_LENGTH 6 |
63 | 52 | ||
64 | /* mask for dynamic filetype info in attribute */ | 53 | /* mask for dynamic filetype info in attribute */ |
65 | #define FILETYPES_MASK 0xFF00 | 54 | #define FILETYPES_MASK 0xFF00 |
66 | 55 | #define ROCK_EXTENSION "rock" | |
67 | /* filenames */ | 56 | |
68 | #define ROCK_EXTENSION ".rock" | 57 | struct file_type { |
69 | #define VIEWERS_CONFIG ROCKBOX_DIR "/viewers.config" | 58 | ICON_NO_CONST icon; /* the icon which shall be used for it, NOICON if unknown */ |
70 | #define VIEWERS_DIR ROCKBOX_DIR "/viewers" | 59 | bool viewer; /* true if the rock is in viewers, false if in rocks */ |
71 | 60 | unsigned char attr; /* FILETYPES_MASK >> 8 */ | |
72 | /* global variables */ | 61 | char* plugin; /* Which plugin to use, NULL if unknown, or builtin */ |
73 | static int cnt_filetypes; | 62 | char* extension; /* NULL for none */ |
74 | static int cnt_exttypes; | 63 | }; |
75 | static struct ext_type exttypes [MAX_EXTTYPES]; | ||
76 | static struct file_type filetypes[MAX_FILETYPES]; | 64 | static struct file_type filetypes[MAX_FILETYPES]; |
77 | static int first_soft_exttype; | 65 | static int filetype_count = 0; |
78 | static int first_soft_filetype; | 66 | static unsigned char heighest_attr = 0; |
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]; | ||
82 | 67 | ||
83 | /* prototypes */ | 68 | static char *filetypes_strdup(char* string) |
84 | #ifdef HAVE_LCD_BITMAP | ||
85 | static char* string2icon(const char*); | ||
86 | static int add_plugin(char*,char*); | ||
87 | #else | ||
88 | static int add_plugin(char*); | ||
89 | #endif | ||
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); | ||
95 | |||
96 | /* initialize dynamic filetypes (called at boot from tree.c) */ | ||
97 | void filetype_init(void) | ||
98 | { | 69 | { |
99 | int cnt,i,ix; | 70 | char *buffer = (char*)buffer_alloc(strlen(string)+1); |
100 | const struct filetype* ftypes; | 71 | strcpy(buffer, string); |
101 | 72 | return buffer; | |
102 | memset(exttypes,0,sizeof(exttypes)); | ||
103 | memset(filetypes,0,sizeof(filetypes)); | ||
104 | next_free_string=string_buffer; | ||
105 | |||
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]; | ||
110 | #else | ||
111 | if (!filetypes[0].icon) | ||
112 | filetypes[0].icon = Icon_Folder; | ||
113 | for (i=1; i < MAX_FILETYPES; i++) | ||
114 | filetypes[i].icon = -1; | ||
115 | #endif | ||
116 | |||
117 | /* register hardcoded filetypes */ | ||
118 | tree_get_filetypes(&ftypes, &cnt); | ||
119 | cnt_exttypes=0; | ||
120 | cnt_filetypes=0; | ||
121 | |||
122 | for (i = 0; i < cnt ; i++) | ||
123 | { | ||
124 | ix = ((ftypes[i].tree_attr & FILETYPES_MASK) >> 8); | ||
125 | if (ix < MAX_FILETYPES && i < MAX_EXTTYPES) | ||
126 | { | ||
127 | #ifdef HAVE_LCD_BITMAP | ||
128 | if (filetypes[ix].icon == NULL) | ||
129 | filetypes[ix].icon=bitmap_icons_6x8[ftypes[i].icon]; | ||
130 | #else | ||
131 | if (filetypes[ix].icon == -1) | ||
132 | filetypes[ix].icon=ftypes[i].icon; | ||
133 | #endif | ||
134 | if (ix > cnt_filetypes) | ||
135 | cnt_filetypes=ix; | ||
136 | exttypes[cnt_exttypes].type=&filetypes[ix]; | ||
137 | exttypes[cnt_exttypes].extension=ftypes[i].extension; | ||
138 | cnt_exttypes++; | ||
139 | } | ||
140 | } | ||
141 | first_soft_exttype=cnt_exttypes; | ||
142 | cnt_filetypes++; | ||
143 | first_soft_filetype=cnt_filetypes; | ||
144 | |||
145 | /* register dynamic filetypes */ | ||
146 | read_config(VIEWERS_CONFIG); | ||
147 | scan_plugins(); | ||
148 | } | 73 | } |
74 | static void read_builtin_types(void); | ||
75 | static void read_config(char* config_file); | ||
149 | 76 | ||
150 | /* get icon */ | 77 | void filetype_init(void) |
151 | #ifdef HAVE_LCD_BITMAP | ||
152 | const unsigned char* filetype_get_icon(int attr) | ||
153 | #else | ||
154 | int filetype_get_icon(int attr) | ||
155 | #endif | ||
156 | { | 78 | { |
157 | int ix; | 79 | /* set the directory item first */ |
158 | 80 | filetypes[0].extension = NULL; | |
159 | ix = find_attr_index(attr); | 81 | filetypes[0].plugin = NULL; |
160 | 82 | filetypes[0].attr = 0; | |
161 | if (ix < 0) | 83 | filetypes[0].icon = |
162 | { | ||
163 | #ifdef HAVE_LCD_BITMAP | 84 | #ifdef HAVE_LCD_BITMAP |
164 | return NULL; | 85 | (ICON_NO_CONST)&bitmap_icons_6x8[Icon_Folder]; |
165 | #else | 86 | #else |
166 | return Icon_Unknown; | 87 | (ICON_NO_CONST)Icon_Folder; |
167 | #endif | 88 | #endif |
168 | } | 89 | filetype_count = 1; |
169 | else | 90 | read_builtin_types(); |
170 | { | 91 | read_config(VIEWERS_CONFIG); |
171 | return filetypes[ix].icon; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | /* get plugin */ | ||
176 | char* filetype_get_plugin(const struct entry* file) | ||
177 | { | ||
178 | int ix; | ||
179 | |||
180 | ix=find_attr_index(file->attr); | ||
181 | |||
182 | if (ix < 0) | ||
183 | { | ||
184 | return NULL; | ||
185 | } | ||
186 | |||
187 | if ((filetypes[ix].plugin == NULL) || | ||
188 | (strlen(filetypes[ix].plugin) > MAX_PLUGIN_LENGTH)) | ||
189 | return NULL; | ||
190 | |||
191 | snprintf(plugin_name, sizeof(plugin_name), | ||
192 | "%s/%s.rock", ROCKBOX_DIR, filetypes[ix].plugin); | ||
193 | |||
194 | return plugin_name; | ||
195 | } | ||
196 | |||
197 | /* check if filetype is supported */ | ||
198 | bool filetype_supported(int attr) | ||
199 | { | ||
200 | int ix; | ||
201 | |||
202 | ix=find_attr_index(attr); | ||
203 | |||
204 | /* hard filetypes and soft filetypes with plugins is supported */ | ||
205 | if (ix > 0) | ||
206 | if (filetypes[ix].plugin || ix < first_soft_filetype) | ||
207 | return true; | ||
208 | |||
209 | return false; | ||
210 | } | ||
211 | |||
212 | /* get the "dynamic" attribute for an extension */ | ||
213 | int filetype_get_attr(const char* name) | ||
214 | { | ||
215 | int i; | ||
216 | const char *cp = strrchr(name,'.'); | ||
217 | |||
218 | if (!cp) /* no extension? -> can't be a supported type */ | ||
219 | return 0; | ||
220 | cp++; | ||
221 | |||
222 | for (i=0; i < cnt_exttypes; i++) | ||
223 | { | ||
224 | if (exttypes[i].extension) | ||
225 | { | ||
226 | if (!strcasecmp(cp,exttypes[i].extension)) | ||
227 | { | ||
228 | return ((((unsigned long)exttypes[i].type - | ||
229 | (unsigned long)&filetypes[0]) / | ||
230 | sizeof(struct file_type)) << 8); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | /* fill a menu list with viewers (used in onplay.c) */ | ||
239 | int filetype_load_menu(struct menu_item* menu,int max_items) | ||
240 | { | ||
241 | int i; | ||
242 | char *cp; | ||
243 | int cnt=0; | ||
244 | |||
245 | for (i=0; i < cnt_filetypes; i++) | ||
246 | { | ||
247 | if (filetypes[i].plugin) | ||
248 | { | ||
249 | int j; | ||
250 | for (j=0;j<cnt;j++) /* check if the plugin is in the list yet */ | ||
251 | { | ||
252 | if (!strcmp(menu[j].desc,filetypes[i].plugin)) | ||
253 | break; | ||
254 | } | ||
255 | if (j<cnt) continue; /* it is so grab the next plugin */ | ||
256 | cp=strrchr(filetypes[i].plugin,'/'); | ||
257 | if (cp) cp++; | ||
258 | else cp=filetypes[i].plugin; | ||
259 | menu[cnt].desc = (unsigned char *)cp; | ||
260 | cnt++; | ||
261 | if (cnt == max_items) | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | return cnt; | ||
266 | } | 92 | } |
267 | 93 | ||
268 | /* start a plugin with an argument (called from onplay.c) */ | 94 | /* remove all white spaces from string */ |
269 | int filetype_load_plugin(const char* plugin, char* file) | 95 | static void rm_whitespaces(char* str) |
270 | { | 96 | { |
271 | int fd; | 97 | char *s = str; |
272 | snprintf(plugin_name,sizeof(plugin_name),"%s/%s.rock", | 98 | while (*str) |
273 | VIEWERS_DIR,plugin); | ||
274 | if ((fd = open(plugin_name,O_RDONLY))>=0) | ||
275 | { | 99 | { |
276 | close(fd); | 100 | if (!isspace(*str)) |
277 | return plugin_load(plugin_name,file); | ||
278 | } | ||
279 | else | ||
280 | { | ||
281 | snprintf(plugin_name,sizeof(plugin_name),"%s/%s.rock", | ||
282 | PLUGIN_DIR,plugin); | ||
283 | if ((fd = open(plugin_name,O_RDONLY))>=0) | ||
284 | { | 101 | { |
285 | close(fd); | 102 | *s = *str; |
286 | return plugin_load(plugin_name,file); | 103 | s++; |
287 | } | 104 | } |
105 | str++; | ||
288 | } | 106 | } |
289 | return PLUGIN_ERROR; | 107 | *s = '\0'; |
290 | } | 108 | } |
291 | 109 | ||
292 | /* get index to filetypes[] from the file attribute */ | 110 | static void read_builtin_types(void) |
293 | static int find_attr_index(int attr) | ||
294 | { | 111 | { |
295 | int ix; | 112 | const struct filetype *types; |
296 | ix = ((attr & FILETYPES_MASK) >> 8); | 113 | int count, i; |
297 | 114 | tree_get_filetypes(&types, &count); | |
298 | if ((attr & ATTR_DIRECTORY)==ATTR_DIRECTORY) | 115 | for(i=0; i<count && (filetype_count < MAX_FILETYPES); i++) |
299 | { | ||
300 | ix=0; | ||
301 | } | ||
302 | else | ||
303 | { | 116 | { |
304 | if (ix==0) | 117 | filetypes[filetype_count].extension = types[i].extension; |
305 | ix=-1; | 118 | filetypes[filetype_count].plugin = NULL; |
306 | if (ix > cnt_filetypes) | 119 | filetypes[filetype_count].attr = types[i].tree_attr>>8; |
307 | ix=-1; | 120 | if (filetypes[filetype_count].attr > heighest_attr) |
308 | else | 121 | heighest_attr = filetypes[filetype_count].attr; |
309 | if ((filetypes[ix].plugin == NULL) && | 122 | filetypes[filetype_count].icon = |
310 | #ifdef HAVE_LCD_BITMAP | 123 | #ifdef HAVE_LCD_BITMAP |
311 | (filetypes[ix].icon == NULL) | 124 | (ICON_NO_CONST)&bitmap_icons_6x8[types[i].icon]; |
312 | #else | 125 | #else |
313 | (filetypes[ix].icon == -1) | 126 | (ICON_NO_CONST)Icon_Folder; |
314 | #endif | 127 | #endif |
315 | ) | 128 | filetype_count++; |
316 | ix=-1; | ||
317 | } | 129 | } |
318 | |||
319 | return ix; | ||
320 | } | 130 | } |
321 | 131 | ||
322 | /* scan the plugin directory and register filetypes */ | 132 | static void read_config(char* config_file) |
323 | static void scan_plugins(void) | ||
324 | { | 133 | { |
325 | DIR *dir; | 134 | char line[64], *s, *e; |
326 | struct dirent *entry; | 135 | char extension[8], plugin[32]; |
327 | char* cp; | 136 | #ifdef HAVE_LCD_BITMAP |
328 | char* dot; | 137 | char icon[ICON_LENGTH]; |
329 | char* dash; | 138 | int good_icon; |
330 | int ix; | 139 | #endif |
331 | int i; | 140 | bool viewer; |
332 | bool found; | 141 | int fd = open(config_file, O_RDONLY); |
333 | 142 | if (fd < 0) | |
334 | dir = opendir(VIEWERS_DIR); | ||
335 | if(!dir) | ||
336 | return; | 143 | return; |
337 | 144 | /* config file is in the for | |
338 | while (true) | 145 | <extension>,<plugin>,<icon code> |
146 | ignore line if either of the first two are missing */ | ||
147 | while (read_line(fd, line, 64) > 0) | ||
339 | { | 148 | { |
340 | /* exttypes[] full, bail out */ | 149 | if (filetype_count >= MAX_FILETYPES) |
341 | if (cnt_exttypes >= MAX_EXTTYPES) | ||
342 | { | ||
343 | gui_syncsplash(HZ, str(LANG_FILETYPES_EXTENSION_FULL)); | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | /* filetypes[] full, bail out */ | ||
348 | if (cnt_filetypes >= MAX_FILETYPES) | ||
349 | { | 150 | { |
350 | gui_syncsplash(HZ, str(LANG_FILETYPES_FULL)); | 151 | gui_syncsplash(HZ, str(LANG_FILETYPES_FULL)); |
351 | break; | 152 | break; |
352 | } | 153 | } |
353 | 154 | rm_whitespaces(line); | |
354 | entry = readdir(dir); | 155 | /* get the extention */ |
355 | 156 | s = line; | |
356 | if (!entry) | 157 | e = strchr(s, ','); |
357 | break; | 158 | if (!e) |
358 | |||
359 | /* skip directories */ | ||
360 | if ((entry->attribute & ATTR_DIRECTORY)) | ||
361 | continue; | ||
362 | |||
363 | /* Skip FAT volume ID */ | ||
364 | if (entry->attribute & ATTR_VOLUME_ID) | ||
365 | continue; | 159 | continue; |
366 | 160 | *e = '\0'; | |
367 | /* filter out dotfiles and hidden files */ | 161 | strcpy(extension, s); |
368 | if ((entry->d_name[0]=='.') || | 162 | |
369 | (entry->attribute & ATTR_HIDDEN)) { | 163 | /* get the plugin */ |
164 | s = e+1; | ||
165 | e = strchr(s, '/'); | ||
166 | if (!e) | ||
370 | continue; | 167 | continue; |
371 | } | 168 | *e = '\0'; |
372 | 169 | if (!strcasecmp("viewers", s)) | |
373 | /* filter out non rock files */ | 170 | viewer = true; |
374 | if (strcasecmp((char *)&entry->d_name[strlen((char *)entry->d_name) - | 171 | else |
375 | sizeof(ROCK_EXTENSION) + 1], | 172 | viewer = false; |
376 | ROCK_EXTENSION)) { | 173 | s = e+1; |
174 | e = strchr(s, ','); | ||
175 | if (!e) | ||
377 | continue; | 176 | continue; |
378 | } | 177 | *e = '\0'; |
379 | 178 | strcpy(plugin, s); | |
380 | /* filter out to long filenames */ | 179 | /* ok, store this plugin/extension, check icon after */ |
381 | if (strlen((char *)entry->d_name) > MAX_PLUGIN_LENGTH + 5) | 180 | filetypes[filetype_count].extension = filetypes_strdup(extension); |
181 | filetypes[filetype_count].plugin = filetypes_strdup(plugin); | ||
182 | filetypes[filetype_count].viewer = viewer; | ||
183 | filetypes[filetype_count].attr = heighest_attr +1; | ||
184 | heighest_attr++; | ||
185 | /* get the icon */ | ||
186 | #ifdef HAVE_LCD_BITMAP | ||
187 | s = e+1; | ||
188 | good_icon = 1; | ||
189 | if (strlen(s) == 12) | ||
382 | { | 190 | { |
383 | gui_syncsplash(HZ, str(LANG_FILETYPES_PLUGIN_NAME_LONG)); | 191 | int i, j; |
384 | continue; | 192 | char val[2]; |
385 | } | 193 | for (i = 0; good_icon && i < ICON_LENGTH; i++) |
386 | |||
387 | dot=strrchr((char *)entry->d_name,'.'); | ||
388 | *dot='\0'; | ||
389 | dash=strchr((char *)entry->d_name,'-'); | ||
390 | |||
391 | /* add plugin and extension */ | ||
392 | if (dash) | ||
393 | { | ||
394 | *dash='\0'; | ||
395 | ix=(filetype_get_attr((char *)entry->d_name) >> 8); | ||
396 | if (!ix) | ||
397 | { | 194 | { |
398 | cp=get_string((char *)entry->d_name); | 195 | for (j=0; good_icon && j<2; j++) |
399 | if (cp) | ||
400 | { | 196 | { |
401 | exttypes[cnt_exttypes].extension=cp; | 197 | val[j] = tolower(s[i*2+j]); |
402 | exttypes[cnt_exttypes].type=&filetypes[cnt_filetypes]; | 198 | if (val[j] >= 'a' && val[j] <= 'f') |
403 | #ifdef HAVE_LCD_BITMAP | ||
404 | exttypes[cnt_exttypes].type->icon = bitmap_icons_6x8[Icon_Plugin]; | ||
405 | #else | ||
406 | exttypes[cnt_exttypes].type->icon = Icon_Plugin; | ||
407 | #endif | ||
408 | cnt_exttypes++; | ||
409 | |||
410 | *dash='-'; | ||
411 | cp=get_string((char *)entry->d_name); | ||
412 | if (cp) | ||
413 | { | 199 | { |
414 | filetypes[cnt_filetypes].plugin=cp; | 200 | val[j] = val[j] - 'a' + 10; |
415 | cnt_filetypes++; | ||
416 | } | 201 | } |
417 | else | 202 | else if (val[j] >= '0' && val[j] <= '9') |
418 | break; | ||
419 | } | ||
420 | else | ||
421 | break; | ||
422 | } | ||
423 | else | ||
424 | { | ||
425 | *dash='-'; | ||
426 | if (!filetypes[ix].plugin) | ||
427 | { | ||
428 | cp=get_string((char *)entry->d_name); | ||
429 | if (cp) | ||
430 | { | 203 | { |
431 | filetypes[cnt_filetypes].plugin=cp; | 204 | val[j] = val[j] - '0'; |
432 | cnt_filetypes++; | ||
433 | } | 205 | } |
434 | else | 206 | else |
435 | break; | 207 | good_icon = 0; |
436 | } | 208 | } |
209 | icon[i]=((val[0]<<4) | val[1]); | ||
437 | } | 210 | } |
438 | *dash='-'; | ||
439 | } | 211 | } |
440 | /* add plugin only */ | 212 | if (good_icon) |
441 | else | ||
442 | { | 213 | { |
443 | found=false; | 214 | filetypes[filetype_count].icon = |
444 | for (i = first_soft_filetype; i < cnt_filetypes; i++) | 215 | (ICON_NO_CONST)buffer_alloc(ICON_LENGTH); |
445 | { | 216 | memcpy(filetypes[filetype_count].icon, icon, ICON_LENGTH); |
446 | if (filetypes[i].plugin) | ||
447 | if (!strcasecmp(filetypes[i].plugin, (char *)entry->d_name)) | ||
448 | { | ||
449 | found=true; | ||
450 | break; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | if (!found) | ||
455 | { | ||
456 | cp=get_string((char *)entry->d_name); | ||
457 | if (cp) | ||
458 | { | ||
459 | filetypes[cnt_filetypes].plugin=cp; | ||
460 | filetypes[cnt_filetypes].no_extension=true; | ||
461 | cnt_filetypes++; | ||
462 | } | ||
463 | else | ||
464 | break; | ||
465 | } | ||
466 | } | 217 | } |
467 | *dot='.'; | 218 | else |
219 | filetypes[filetype_count].icon = NOICON; | ||
220 | #else | ||
221 | filetypes[filetype_count].icon = Icon_Unknown; | ||
222 | #endif | ||
223 | filetype_count++; | ||
468 | } | 224 | } |
469 | closedir(dir); | ||
470 | } | 225 | } |
471 | 226 | ||
472 | #ifdef HAVE_LCD_BITMAP | 227 | int filetype_get_attr(const char* file) |
473 | static int add_plugin(char *plugin, char *icon) | ||
474 | #else | ||
475 | static int add_plugin(char *plugin) | ||
476 | #endif | ||
477 | { | 228 | { |
478 | char *cp; | 229 | char *extension = strrchr(file, '.'); |
479 | int i; | 230 | int i; |
480 | 231 | if (!extension) | |
481 | if (!plugin) | ||
482 | return 0; | 232 | return 0; |
483 | 233 | extension++; | |
484 | #if 0 | 234 | for (i=0; i<filetype_count; i++) |
485 | /* starting now, Oct 2005, the plugins are given without extension in the | ||
486 | viewers.config file */ | ||
487 | cp=strrchr(plugin, '.'); | ||
488 | if (cp) | ||
489 | *cp='\0'; | ||
490 | #endif | ||
491 | |||
492 | for (i=first_soft_filetype; i < cnt_filetypes; i++) | ||
493 | { | 235 | { |
494 | if (filetypes[i].plugin) | 236 | if (filetypes[i].extension && |
495 | { | 237 | !strcasecmp(extension, filetypes[i].extension)) |
496 | if (!strcasecmp(plugin, filetypes[i].plugin)) | 238 | return (filetypes[i].attr<<8)&TREE_ATTR_MASK; |
497 | { | ||
498 | #ifdef HAVE_LCD_BITMAP | ||
499 | if (filetypes[i].icon == NULL && icon) | ||
500 | { | ||
501 | cp = string2icon(icon); | ||
502 | if (cp) | ||
503 | filetypes[cnt_filetypes].icon = (unsigned char *)cp; | ||
504 | else | ||
505 | return 0; | ||
506 | } | ||
507 | #endif | ||
508 | return i; | ||
509 | } | ||
510 | } | ||
511 | } | 239 | } |
240 | return 0; | ||
241 | } | ||
512 | 242 | ||
513 | /* new plugin */ | 243 | static int find_attr(int attr) |
514 | cp = get_string(plugin); | 244 | { |
515 | if (cp) | 245 | int i; |
516 | { | 246 | /* skip the directory item */ |
517 | filetypes[cnt_filetypes].plugin = cp; | 247 | if ((attr & ATTR_DIRECTORY)==ATTR_DIRECTORY) |
518 | #ifdef HAVE_LCD_BITMAP | ||
519 | /* add icon */ | ||
520 | if (icon) | ||
521 | { | ||
522 | cp = string2icon(icon); | ||
523 | if (cp) | ||
524 | filetypes[cnt_filetypes].icon = (unsigned char *)cp; | ||
525 | else | ||
526 | return 0; | ||
527 | } | ||
528 | #endif | ||
529 | } | ||
530 | else | ||
531 | { | ||
532 | return 0; | 248 | return 0; |
249 | for (i=1; i<filetype_count; i++) | ||
250 | { | ||
251 | if ((attr>>8) == filetypes[i].attr) | ||
252 | return i; | ||
533 | } | 253 | } |
534 | 254 | return -1; | |
535 | cnt_filetypes++; | ||
536 | return cnt_filetypes - 1; | ||
537 | } | 255 | } |
538 | 256 | ||
539 | /* read config file (or cahe file) */ | 257 | ICON filetype_get_icon(int attr) |
540 | static bool read_config(const char* file) | ||
541 | { | 258 | { |
542 | enum {extension, | 259 | int index = find_attr(attr); |
543 | plugin, | 260 | if (index < 0) |
544 | #ifdef HAVE_LCD_BITMAP | 261 | return NOICON; |
545 | icon, | 262 | return (ICON)filetypes[index].icon; |
546 | #endif | 263 | } |
547 | last}; | ||
548 | 264 | ||
549 | int i,ix; | 265 | char* filetype_get_plugin(const struct entry* file) |
550 | int fd; | 266 | { |
551 | char* end; | 267 | static char plugin_name[MAX_PATH]; |
552 | char* cp; | 268 | int index = find_attr(file->attr); |
553 | char* str[last]; | 269 | if (index < 0) |
554 | char buf[80]; | 270 | return NULL; |
271 | snprintf(plugin_name, MAX_PATH, "%s/%s.%s", | ||
272 | filetypes[index].viewer? VIEWERS_DIR: PLUGIN_DIR, | ||
273 | filetypes[index].plugin, ROCK_EXTENSION); | ||
274 | return plugin_name; | ||
275 | } | ||
555 | 276 | ||
556 | fd = open(file, O_RDONLY); | 277 | bool filetype_supported(int attr) |
557 | if (fd < 0) | 278 | { |
558 | return false; | 279 | return find_attr(attr) >= 0; |
280 | } | ||
559 | 281 | ||
560 | while (read_line(fd, buf, sizeof(buf))) | 282 | int filetype_list_viewers(const char* current_file) |
283 | { | ||
284 | int i, count = 0; | ||
285 | char *strings[MAX_FILETYPES/2]; | ||
286 | struct menu_callback_with_desc cb_and_desc = | ||
287 | { NULL, ID2P(LANG_ONPLAY_OPEN_WITH), Icon_Plugin }; | ||
288 | struct menu_item_ex menu; | ||
289 | |||
290 | for (i=0; i<filetype_count && count < (MAX_FILETYPES/2); i++) | ||
561 | { | 291 | { |
562 | if (cnt_exttypes >= MAX_EXTTYPES) | 292 | if (filetypes[i].plugin) |
563 | { | ||
564 | gui_syncsplash(HZ, str(LANG_FILETYPES_EXTENSION_FULL)); | ||
565 | break; | ||
566 | } | ||
567 | |||
568 | if (cnt_filetypes >= MAX_FILETYPES) | ||
569 | { | ||
570 | gui_syncsplash(HZ, str(LANG_FILETYPES_FULL)); | ||
571 | break; | ||
572 | } | ||
573 | |||
574 | /* parse buffer */ | ||
575 | rm_whitespaces(buf); | ||
576 | |||
577 | if (strlen(buf) == 0) | ||
578 | continue; | ||
579 | |||
580 | if (buf[0] == '#') | ||
581 | continue; | ||
582 | |||
583 | memset(str,0,sizeof(str)); | ||
584 | i=0; | ||
585 | cp=buf; | ||
586 | while (*cp==',') { | ||
587 | cp++; | ||
588 | i++; | ||
589 | } | ||
590 | str[i] = strtok_r(cp, ",", &end); | ||
591 | i++; | ||
592 | |||
593 | while (end && i < last) | ||
594 | { | ||
595 | if (end) | ||
596 | { | ||
597 | cp=end; | ||
598 | while (*cp==',') { | ||
599 | cp++; | ||
600 | i++; | ||
601 | } | ||
602 | } | ||
603 | str[i] = strtok_r(NULL, ",", &end); | ||
604 | if (str[i]) | ||
605 | if (!strlen(str[i])) | ||
606 | str[i]=NULL; | ||
607 | i++; | ||
608 | } | ||
609 | |||
610 | /* bail out if no icon and no plugin */ | ||
611 | if (!str[plugin] | ||
612 | #ifdef HAVE_LCD_BITMAP | ||
613 | && !str[icon] | ||
614 | #endif | ||
615 | ) | ||
616 | continue; | ||
617 | |||
618 | /* bail out if no plugin and icon is incorrect*/ | ||
619 | if (!str[plugin] | ||
620 | #ifdef HAVE_LCD_BITMAP | ||
621 | && strlen(str[icon]) != ICON_LENGTH*2 | ||
622 | #endif | ||
623 | ) | ||
624 | continue; | ||
625 | |||
626 | /* bail out if no icon and no plugin and no extension*/ | ||
627 | if (!str[plugin] && | ||
628 | #ifdef HAVE_LCD_BITMAP | ||
629 | !str[icon] && | ||
630 | #endif | ||
631 | !str[extension]) | ||
632 | continue; | ||
633 | |||
634 | /* bail out if we are not able to start plugin from onplay.c ?*/ | ||
635 | if (str[plugin]) | ||
636 | { | ||
637 | if (strlen(str[plugin]) > MAX_PLUGIN_LENGTH) | ||
638 | { | ||
639 | gui_syncsplash(HZ, str(LANG_FILETYPES_PLUGIN_NAME_LONG)); | ||
640 | str[plugin] = NULL; | ||
641 | continue; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | ix=0; | ||
646 | /* if extension already exist don't add a new one */ | ||
647 | for (i=0; i < cnt_exttypes; i++) | ||
648 | { | ||
649 | if (!strcasecmp(str[extension],exttypes[i].extension)) | ||
650 | { | ||
651 | #ifdef HAVE_LCD_BITMAP | ||
652 | ix=add_plugin(str[plugin],NULL); | ||
653 | if (ix) | ||
654 | { | ||
655 | if (str[icon] && filetypes[ix].icon == NULL) | ||
656 | { | ||
657 | if (exttypes[i].type->icon == NULL) | ||
658 | { | ||
659 | cp = string2icon(str[icon]); | ||
660 | if (cp) | ||
661 | exttypes[i].type->icon = (unsigned char *)cp; | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | #else | ||
666 | ix=add_plugin(str[plugin]); | ||
667 | #endif | ||
668 | if (exttypes[i].type == NULL) | ||
669 | { | ||
670 | exttypes[i].type = &filetypes[ix]; | ||
671 | } | ||
672 | break; | ||
673 | } | ||
674 | } | ||
675 | if (ix) | ||
676 | continue; | ||
677 | |||
678 | /* add extension */ | ||
679 | if (str[extension]) | ||
680 | { | 293 | { |
681 | #ifdef HAVE_LCD_BITMAP | 294 | int j; |
682 | ix=add_plugin(str[plugin],str[icon]); | 295 | for (j=0;j<count;j++) /* check if the plugin is in the list yet */ |
683 | #else | ||
684 | ix=add_plugin(str[plugin]); | ||
685 | #endif | ||
686 | if (ix) | ||
687 | { | 296 | { |
688 | cp=get_string(str[extension]); | 297 | if (!strcmp(strings[j], filetypes[i].plugin)) |
689 | if (cp) | ||
690 | { | ||
691 | exttypes[cnt_exttypes].extension = cp; | ||
692 | |||
693 | exttypes[cnt_exttypes].type = &filetypes[ix]; | ||
694 | cnt_exttypes++; | ||
695 | filetypes[i].no_extension=false; | ||
696 | } | ||
697 | else | ||
698 | { | ||
699 | break; | 298 | break; |
700 | } | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | break; | ||
705 | } | 299 | } |
300 | if (j<count) | ||
301 | continue; /* it is so grab the next plugin */ | ||
302 | strings[count] = filetypes[i].plugin; | ||
303 | count++; | ||
706 | } | 304 | } |
707 | else | ||
708 | { | ||
709 | #ifdef HAVE_LCD_BITMAP | ||
710 | ix=add_plugin(str[plugin],str[icon]); | ||
711 | #else | ||
712 | ix=add_plugin(str[plugin]); | ||
713 | #endif | ||
714 | filetypes[ix].no_extension=true; | ||
715 | if (!i) | ||
716 | break; | ||
717 | } | ||
718 | } | ||
719 | close(fd); | ||
720 | |||
721 | return true; | ||
722 | } | ||
723 | |||
724 | #ifdef HAVE_LCD_BITMAP | ||
725 | /* convert an ascii hexadecimal icon to a binary icon */ | ||
726 | static char* string2icon(const char* str) | ||
727 | { | ||
728 | char tmp[ICON_LENGTH*2]; | ||
729 | char *cp; | ||
730 | int i; | ||
731 | |||
732 | if (strlen(str)!=ICON_LENGTH*2) | ||
733 | return NULL; | ||
734 | |||
735 | if ((sizeof(string_buffer) + | ||
736 | (unsigned long) string_buffer - | ||
737 | (unsigned long) next_free_string) < ICON_LENGTH) | ||
738 | { | ||
739 | gui_syncsplash(HZ, str(LANG_FILETYPES_STRING_BUFFER_EMPTY)); | ||
740 | return NULL; | ||
741 | } | 305 | } |
742 | 306 | #ifndef HAVE_LCD_BITMAP | |
743 | for (i=0; i<12; i++) | 307 | if (count == 0) |
744 | { | 308 | { |
745 | if (str[i] >= '0' && str[i] <= '9') | 309 | /* FIX: translation! */ |
746 | { | 310 | gui_syncsplash(HZ*2, (unsigned char *)"No viewers found"); |
747 | tmp[i]=str[i]-'0'; | 311 | return PLUGIN_OK; |
748 | continue; | ||
749 | } | ||
750 | |||
751 | if (str[i] >= 'a' && str[i] <= 'f') | ||
752 | { | ||
753 | tmp[i]=str[i]-'a'+10; | ||
754 | continue; | ||
755 | } | ||
756 | |||
757 | if (str[i] >= 'A' && str[i] <= 'F') | ||
758 | { | ||
759 | tmp[i]=str[i]-'A'+10; | ||
760 | continue; | ||
761 | } | ||
762 | |||
763 | return NULL; | ||
764 | } | 312 | } |
765 | |||
766 | cp=next_free_string; | ||
767 | for (i = 0; i < ICON_LENGTH; i++) | ||
768 | cp[i]=((tmp[i*2]<<4) | tmp[i*2+1]); | ||
769 | |||
770 | next_free_string=&next_free_string[ICON_LENGTH]; | ||
771 | return cp; | ||
772 | } | ||
773 | #endif | 313 | #endif |
314 | menu.flags = MT_RETURN_ID|MENU_HAS_DESC|MENU_ITEM_COUNT(count); | ||
315 | menu.strings = (const char**)strings; | ||
316 | menu.callback_and_desc = &cb_and_desc; | ||
317 | i = do_menu(&menu, NULL); | ||
318 | if (i >= 0) | ||
319 | return filetype_load_plugin(strings[i], (void*)current_file); | ||
320 | return i; | ||
321 | } | ||
774 | 322 | ||
775 | /* get string from buffer */ | 323 | int filetype_load_plugin(const char* plugin, char* file) |
776 | static char* get_string(const char* str) | ||
777 | { | 324 | { |
778 | unsigned int l=strlen(str)+1; | 325 | int fd; |
779 | char* cp; | 326 | char plugin_name[MAX_PATH]; |
780 | 327 | snprintf(plugin_name, sizeof(plugin_name), "%s/%s.%s", | |
781 | if (!str) | 328 | VIEWERS_DIR, plugin, ROCK_EXTENSION); |
782 | return NULL; | 329 | if ((fd = open(plugin_name,O_RDONLY))>=0) |
783 | |||
784 | if (l <= (sizeof(string_buffer) + | ||
785 | (unsigned long) string_buffer - | ||
786 | (unsigned long) next_free_string)) | ||
787 | { | 330 | { |
788 | strcpy(next_free_string, str); | 331 | close(fd); |
789 | cp=next_free_string; | 332 | return plugin_load(plugin_name,file); |
790 | next_free_string=&next_free_string[l]; | ||
791 | return cp; | ||
792 | } | 333 | } |
793 | else | 334 | else |
794 | { | 335 | { |
795 | gui_syncsplash(HZ, str(LANG_FILETYPES_STRING_BUFFER_EMPTY)); | 336 | snprintf(plugin_name, sizeof(plugin_name), "%s/%s.%s", |
796 | return NULL; | 337 | PLUGIN_DIR, plugin, ROCK_EXTENSION); |
797 | } | 338 | if ((fd = open(plugin_name,O_RDONLY))>=0) |
798 | } | ||
799 | |||
800 | /* remove all white spaces from string */ | ||
801 | static void rm_whitespaces(char* str) | ||
802 | { | ||
803 | char *cp, *free; | ||
804 | |||
805 | cp=str; | ||
806 | free=cp; | ||
807 | |||
808 | while (cp < &str[strlen(str)]) | ||
809 | { | ||
810 | switch (*cp) | ||
811 | { | 339 | { |
812 | case ' ' : | 340 | close(fd); |
813 | case '\t' : | 341 | return plugin_load(plugin_name,file); |
814 | case '\r' : | ||
815 | break; | ||
816 | |||
817 | default: | ||
818 | *free=*cp; | ||
819 | free++; | ||
820 | break; | ||
821 | } | 342 | } |
822 | cp++; | ||
823 | } | 343 | } |
824 | 344 | return PLUGIN_ERROR; | |
825 | *free='\0'; | ||
826 | } | 345 | } |