summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/filetypes.c905
-rw-r--r--apps/filetypes.h40
-rw-r--r--apps/gui/icon.h2
-rw-r--r--apps/main.c3
-rw-r--r--apps/onplay.c21
-rw-r--r--apps/settings.h6
-rw-r--r--apps/tree.c1
7 files changed, 238 insertions, 740 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" 57struct 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 */
73static int cnt_filetypes; 62 char* extension; /* NULL for none */
74static int cnt_exttypes; 63};
75static struct ext_type exttypes [MAX_EXTTYPES];
76static struct file_type filetypes[MAX_FILETYPES]; 64static struct file_type filetypes[MAX_FILETYPES];
77static int first_soft_exttype; 65static int filetype_count = 0;
78static int first_soft_filetype; 66static unsigned char heighest_attr = 0;
79static char* next_free_string;
80static char plugin_name[sizeof(VIEWERS_DIR) + 7 + MAX_PLUGIN_LENGTH];
81static char string_buffer[STRING_BUFFER_SIZE];
82 67
83/* prototypes */ 68static char *filetypes_strdup(char* string)
84#ifdef HAVE_LCD_BITMAP
85static char* string2icon(const char*);
86static int add_plugin(char*,char*);
87#else
88static int add_plugin(char*);
89#endif
90static char* get_string(const char*);
91static int find_attr_index(int);
92static bool read_config(const char*);
93static void rm_whitespaces(char*);
94static void scan_plugins(void);
95
96/* initialize dynamic filetypes (called at boot from tree.c) */
97void 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}
74static void read_builtin_types(void);
75static void read_config(char* config_file);
149 76
150/* get icon */ 77void filetype_init(void)
151#ifdef HAVE_LCD_BITMAP
152const unsigned char* filetype_get_icon(int attr)
153#else
154int 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 */
176char* 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 */
198bool 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 */
213int 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) */
239int 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 */
269int filetype_load_plugin(const char* plugin, char* file) 95static 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 */ 110static void read_builtin_types(void)
293static 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 */ 132static void read_config(char* config_file)
323static 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 227int filetype_get_attr(const char* file)
473static int add_plugin(char *plugin, char *icon)
474#else
475static 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 */ 243static 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) */ 257ICON filetype_get_icon(int attr)
540static 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; 265char* 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); 277bool 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))) 282int 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 */
726static 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 */ 323int filetype_load_plugin(const char* plugin, char* file)
776static 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 */
801static 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}
diff --git a/apps/filetypes.h b/apps/filetypes.h
index 7416c93b00..d2556c1d95 100644
--- a/apps/filetypes.h
+++ b/apps/filetypes.h
@@ -22,32 +22,24 @@
22#include <stdbool.h> 22#include <stdbool.h>
23#include <tree.h> 23#include <tree.h>
24#include <menu.h> 24#include <menu.h>
25 25/* init the filetypes structs.
26int filetype_get_attr(const char*); 26 uses audio buffer for storage, so call early in init... */
27#ifdef HAVE_LCD_BITMAP
28const unsigned char* filetype_get_icon(int);
29#else
30int filetype_get_icon(int);
31#endif
32char* filetype_get_plugin(const struct entry*);
33void filetype_init(void); 27void filetype_init(void);
34bool filetype_supported(int);
35int filetype_load_menu(struct menu_item*, int);
36int filetype_load_plugin(const char*, char*);
37 28
38struct file_type { 29/* Return the attribute (TREE_ATTR_*) of the file */
39#ifdef HAVE_LCD_BITMAP 30int filetype_get_attr(const char* file);
40 const unsigned char* icon; /* the icon which shall be used for it, NULL if unknown */ 31ICON filetype_get_icon(int attr);
41#else 32/* return the plugin filename associated with the file */
42 int icon; /* the icon which shall be used for it, -1 if unknown */ 33char* filetype_get_plugin(const struct entry* file);
43#endif 34
44 char* plugin; /* Which plugin to use, NULL if unknown */ 35/* returns true if the attr is supported */
45 bool no_extension; 36bool filetype_supported(int attr);
46}; 37
38/* List avialable viewers */
39int filetype_list_viewers(const char* current_file);
40
41/* start a plugin with file as the argument (called from onplay.c) */
42int filetype_load_plugin(const char* plugin, char* file);
47 43
48struct ext_type {
49 char* extension; /* extension for which the file type is recognized */
50 struct file_type* type;
51};
52 44
53#endif 45#endif
diff --git a/apps/gui/icon.h b/apps/gui/icon.h
index 9ceda9e933..c717bbc6ea 100644
--- a/apps/gui/icon.h
+++ b/apps/gui/icon.h
@@ -24,9 +24,11 @@
24 * char-based displays and bitmap displays */ 24 * char-based displays and bitmap displays */
25#ifdef HAVE_LCD_BITMAP 25#ifdef HAVE_LCD_BITMAP
26typedef const unsigned char * ICON; 26typedef const unsigned char * ICON;
27typedef unsigned char * ICON_NO_CONST;
27#define NOICON NULL 28#define NOICON NULL
28#else 29#else
29typedef long ICON; 30typedef long ICON;
31#define ICON_NO_CONST ICON
30#define NOICON -1 32#define NOICON -1
31#endif 33#endif
32 34
diff --git a/apps/main.c b/apps/main.c
index c1f818be7f..27698e35e0 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -29,6 +29,7 @@
29#include "kernel.h" 29#include "kernel.h"
30#include "button.h" 30#include "button.h"
31#include "tree.h" 31#include "tree.h"
32#include "filetypes.h"
32#include "panic.h" 33#include "panic.h"
33#include "menu.h" 34#include "menu.h"
34#include "system.h" 35#include "system.h"
@@ -258,6 +259,7 @@ static void init(void)
258#endif 259#endif
259 sleep(HZ/2); 260 sleep(HZ/2);
260 tree_init(); 261 tree_init();
262 filetype_init();
261 playlist_init(); 263 playlist_init();
262 264
263#if CONFIG_CODEC != SWCODEC 265#if CONFIG_CODEC != SWCODEC
@@ -490,6 +492,7 @@ static void init(void)
490 status_init(); 492 status_init();
491 playlist_init(); 493 playlist_init();
492 tree_init(); 494 tree_init();
495 filetype_init();
493 scrobbler_init(); 496 scrobbler_init();
494 cuesheet_init(); 497 cuesheet_init();
495 498
diff --git a/apps/onplay.c b/apps/onplay.c
index fe70873c56..fb3ed24cfb 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -125,28 +125,9 @@ static bool bookmark_menu(void)
125 125
126static bool list_viewers(void) 126static bool list_viewers(void)
127{ 127{
128 struct menu_item menu[16]; 128 int ret = filetype_list_viewers(selected_file);
129 int m, i, result;
130 int ret = 0;
131
132 i=filetype_load_menu(menu,sizeof(menu)/sizeof(*menu));
133 if (i)
134 {
135 m = menu_init( menu, i, NULL, NULL, NULL, NULL );
136 result = menu_show(m);
137 menu_exit(m);
138 if (result >= 0)
139 ret = filetype_load_plugin((char *)menu[result].desc,selected_file);
140 }
141 else
142 {
143 /* FIX: translation! */
144 gui_syncsplash(HZ*2, (unsigned char *)"No viewers found");
145 }
146
147 if (ret == PLUGIN_USB_CONNECTED) 129 if (ret == PLUGIN_USB_CONNECTED)
148 onplay_result = ONPLAY_RELOAD_DIR; 130 onplay_result = ONPLAY_RELOAD_DIR;
149
150 return false; 131 return false;
151} 132}
152 133
diff --git a/apps/settings.h b/apps/settings.h
index f9e08152af..9921feaba7 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -56,14 +56,16 @@
56#define WPS_DIR ROCKBOX_DIR "/wps" 56#define WPS_DIR ROCKBOX_DIR "/wps"
57#define THEME_DIR ROCKBOX_DIR "/themes" 57#define THEME_DIR ROCKBOX_DIR "/themes"
58#define PLUGIN_DIR ROCKBOX_DIR "/rocks" 58#define PLUGIN_DIR ROCKBOX_DIR "/rocks"
59#define VIEWERS_DIR ROCKBOX_DIR "/viewers"
59#define BACKDROP_DIR ROCKBOX_DIR "/backdrops" 60#define BACKDROP_DIR ROCKBOX_DIR "/backdrops"
60#define REC_BASE_DIR "/recordings" 61#define REC_BASE_DIR "/recordings"
61#define EQS_DIR ROCKBOX_DIR "/eqs" 62#define EQS_DIR ROCKBOX_DIR "/eqs"
62#define CODECS_DIR ROCKBOX_DIR"/codecs" 63#define CODECS_DIR ROCKBOX_DIR"/codecs"
63#define FMPRESET_PATH ROCKBOX_DIR "/fmpresets" 64#define FMPRESET_PATH ROCKBOX_DIR "/fmpresets"
64 65
65#define CONFIGFILE ROCKBOX_DIR "/config.cfg" 66#define VIEWERS_CONFIG ROCKBOX_DIR "/viewers.config"
66#define FIXEDSETTINGSFILE ROCKBOX_DIR "/fixed.cfg" 67#define CONFIGFILE ROCKBOX_DIR "/config.cfg"
68#define FIXEDSETTINGSFILE ROCKBOX_DIR "/fixed.cfg"
67 69
68#define MAX_FILENAME 32 70#define MAX_FILENAME 32
69 71
diff --git a/apps/tree.c b/apps/tree.c
index 14ab8f2577..2b5dba3e18 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -259,7 +259,6 @@ void browse_root(void)
259{ 259{
260 gui_sync_wps_screen_init(); 260 gui_sync_wps_screen_init();
261 261
262 filetype_init();
263 check_rockboxdir(); 262 check_rockboxdir();
264 263
265 strcpy(tc.currdir, "/"); 264 strcpy(tc.currdir, "/");