1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 David Dent
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 /* function return values */
30 TIDY_RETURN_ERROR
= 1,
32 TIDY_RETURN_ABORT
= 3,
40 } tidy_types
[MAX_TYPES
];
42 bool tidy_loaded_and_changed
= false;
44 #define DEFAULT_FILES PLUGIN_APPS_DIR "/disktidy.config"
45 #define CUSTOM_FILES PLUGIN_APPS_DIR "/disktidy_custom.config"
46 void add_item(const char* name
, int index
)
48 rb
->strcpy(tidy_types
[index
].filestring
, name
);
49 if (name
[rb
->strlen(name
)-1] == '/')
51 tidy_types
[index
].directory
= true;
52 tidy_types
[index
].filestring
[rb
->strlen(name
)-1] = '\0';
55 tidy_types
[index
].directory
= false;
57 static int find_file_string(const char *file
, char *last_group
)
60 int i
= 0, idx_last_group
= -1;
62 rb
->strcpy(temp
, file
);
63 if (temp
[rb
->strlen(temp
)-1] == '/')
66 temp
[rb
->strlen(temp
)-1] = '\0';
68 while (i
<tidy_type_count
)
70 if (!rb
->strcmp(tidy_types
[i
].filestring
, temp
) &&
71 folder
== tidy_types
[i
].directory
)
73 else if (!rb
->strcmp(tidy_types
[i
].filestring
, last_group
))
77 /* not found, so insert it into its group */
78 if (file
[0] != '<' && idx_last_group
!= -1)
80 for (i
=idx_last_group
; i
<tidy_type_count
; i
++)
82 if (tidy_types
[i
].filestring
[0] == '<')
88 /* shift items up one */
89 for (i
=tidy_type_count
;i
>idx_last_group
;i
--)
91 rb
->strcpy(tidy_types
[i
].filestring
, tidy_types
[i
-1].filestring
);
92 tidy_types
[i
].directory
= tidy_types
[i
-1].directory
;
93 tidy_types
[i
].remove
= tidy_types
[i
-1].remove
;
96 add_item(file
, idx_last_group
+1);
97 return idx_last_group
+1;
102 bool tidy_load_file(const char* file
)
104 int fd
= rb
->open(file
, O_RDONLY
), i
;
105 char buf
[MAX_PATH
], *str
, *remove
;
106 char last_group
[MAX_PATH
] = "";
110 while ((tidy_type_count
< MAX_TYPES
) &&
111 rb
->read_line(fd
, buf
, MAX_PATH
))
113 if (rb
->settings_parseline(buf
, &str
, &remove
))
115 i
= find_file_string(str
, last_group
);
116 new = (i
>= tidy_type_count
);
117 if (!rb
->strcmp(remove
, "yes"))
118 tidy_types
[i
].remove
= true;
119 else tidy_types
[i
].remove
= false;
127 rb
->strcpy(last_group
, str
);
134 bool tidy_remove_item(char *item
, int attr
)
138 bool ret
= false, rem
= false;
139 for (i
=0; ret
== false && i
< tidy_type_count
; i
++)
141 file
= tidy_types
[i
].filestring
;
142 if (file
[rb
->strlen(file
)-1] == '*')
144 if (!rb
->strncmp(file
, item
, rb
->strlen(file
)-1))
147 else if (!rb
->strcmp(file
, item
))
151 if (!tidy_types
[i
].remove
)
153 if (attr
&ATTR_DIRECTORY
)
154 ret
= tidy_types
[i
].directory
;
161 void tidy_lcd_status(const char *name
, int *removed
)
163 char text
[24]; /* "Cleaned up nnnnn items" */
165 /* display status text */
166 rb
->lcd_clear_display();
167 rb
->lcd_puts(0, 0, "Working ...");
168 rb
->lcd_puts(0, 1, name
);
169 rb
->snprintf(text
, 24, "Cleaned up %d items", *removed
);
170 #ifdef HAVE_LCD_BITMAP
171 rb
->lcd_puts(0, 2, text
);
176 int tidy_path_append_entry(char *path
, struct dirent
*entry
, int *path_length
)
178 int name_len
= rb
->strlen(entry
->d_name
);
179 /* for the special case of path="/" this is one bigger but it's not a problem */
180 int new_length
= *path_length
+ name_len
+ 1;
182 /* check overflow (keep space for trailing zero) */
183 if(new_length
>= MAX_PATH
)
186 /* special case for path <> "/" */
187 if(rb
->strcmp(path
, "/") != 0)
189 rb
->strcat(path
+ *path_length
, "/");
192 /* strcat is unsafe but the previous check normally avoid any problem */
193 /* use path_length to optimise */
195 rb
->strcat(path
+ *path_length
, entry
->d_name
);
196 *path_length
+= name_len
;
201 void tidy_path_remove_entry(char *path
, int old_path_length
, int *path_length
)
203 path
[old_path_length
] = '\0';
204 *path_length
= old_path_length
;
207 /* path is assumed to be array of size MAX_PATH */
208 enum tidy_return
tidy_removedir(char *path
, int *path_length
, int *removed
)
210 /* delete directory */
211 struct dirent
*entry
;
212 enum tidy_return status
= TIDY_RETURN_OK
;
215 int old_path_length
= *path_length
;
217 /* display status text */
218 tidy_lcd_status(path
, removed
);
222 dir
= rb
->opendir(path
);
225 while((status
== TIDY_RETURN_OK
) && ((entry
= rb
->readdir(dir
)) != 0))
228 /* check for user input and usb connect */
229 button
= rb
->get_action(CONTEXT_STD
, TIMEOUT_NOBLOCK
);
230 if (button
== ACTION_STD_CANCEL
)
233 return TIDY_RETURN_ABORT
;
235 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
238 return TIDY_RETURN_USB
;
243 /* get absolute path */
244 /* returns an error if path is too long */
245 if(!tidy_path_append_entry(path
, entry
, path_length
))
249 if (entry
->attribute
& ATTR_DIRECTORY
)
251 /* dir ignore "." and ".." */
252 if ((rb
->strcmp(entry
->d_name
, ".") != 0) && \
253 (rb
->strcmp(entry
->d_name
, "..") != 0))
255 tidy_removedir(path
, path_length
, removed
);
266 tidy_path_remove_entry(path
, old_path_length
, path_length
);
275 status
= TIDY_RETURN_ERROR
;
280 /* path is assumed to be array of size MAX_PATH */
281 enum tidy_return
tidy_clean(char *path
, int *path_length
, int *removed
)
283 /* deletes junk files and dirs left by system */
284 struct dirent
*entry
;
285 enum tidy_return status
= TIDY_RETURN_OK
;
287 int del
; /* has the item been deleted */
289 int old_path_length
= *path_length
;
291 /* display status text */
292 tidy_lcd_status(path
, removed
);
296 dir
= rb
->opendir(path
);
299 while((status
== TIDY_RETURN_OK
) && ((entry
= rb
->readdir(dir
)) != 0))
302 /* check for user input and usb connect */
303 button
= rb
->get_action(CONTEXT_STD
, TIMEOUT_NOBLOCK
);
304 if (button
== ACTION_STD_CANCEL
)
307 return TIDY_RETURN_ABORT
;
309 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
312 return TIDY_RETURN_USB
;
317 if (entry
->attribute
& ATTR_DIRECTORY
)
319 /* directory ignore "." and ".." */
320 if ((rb
->strcmp(entry
->d_name
, ".") != 0) && \
321 (rb
->strcmp(entry
->d_name
, "..") != 0))
325 /* get absolute path */
326 /* returns an error if path is too long */
327 if(!tidy_path_append_entry(path
, entry
, path_length
))
331 if (tidy_remove_item(entry
->d_name
, entry
->attribute
))
334 tidy_removedir(path
, path_length
, removed
);
340 /* dir not deleted so clean it */
341 status
= tidy_clean(path
, path_length
, removed
);
345 tidy_path_remove_entry(path
, old_path_length
, path_length
);
352 if (tidy_remove_item(entry
->d_name
, entry
->attribute
))
354 /* get absolute path */
355 /* returns an error if path is too long */
356 if(!tidy_path_append_entry(path
, entry
, path_length
))
360 *removed
+= 1; /* increment removed files counter */
366 tidy_path_remove_entry(path
, old_path_length
, path_length
);
375 return TIDY_RETURN_ERROR
;
379 enum tidy_return
tidy_do(void)
381 /* clean disk and display num of items removed */
383 enum tidy_return status
;
384 char text
[24]; /* "Cleaned up nnnnn items" */
388 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
392 rb
->strcpy(path
, "/");
393 path_length
= rb
->strlen(path
);
394 status
= tidy_clean(path
, &path_length
, &removed
);
396 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
397 rb
->cpu_boost(false);
400 if ((status
== TIDY_RETURN_OK
) || (status
== TIDY_RETURN_ABORT
))
402 rb
->lcd_clear_display();
403 rb
->snprintf(text
, 24, "Cleaned up %d items", removed
);
404 if (status
== TIDY_RETURN_ABORT
)
406 rb
->splash(HZ
, "User aborted");
407 rb
->lcd_clear_display();
409 rb
->splash(HZ
*2, text
);
414 enum themable_icons
get_icon(int item
, void * data
)
417 if (tidy_types
[item
].filestring
[0] == '<') /* special type */
419 else if (tidy_types
[item
].remove
)
425 static const char* get_name(int selected_item
, void * data
,
426 char * buffer
, size_t buffer_len
)
429 if (tidy_types
[selected_item
].directory
)
431 rb
->snprintf(buffer
, buffer_len
, "%s/",
432 tidy_types
[selected_item
].filestring
);
435 return tidy_types
[selected_item
].filestring
;
438 int list_action_callback(int action
, struct gui_synclist
*lists
)
440 if (action
== ACTION_STD_OK
)
442 int selection
= rb
->gui_synclist_get_sel_pos(lists
);
443 if (tidy_types
[selection
].filestring
[0] == '<')
446 if (!rb
->strcmp(tidy_types
[selection
].filestring
, "< ALL >"))
448 for (i
=0; i
<tidy_type_count
; i
++)
450 if (tidy_types
[i
].filestring
[0] != '<')
451 tidy_types
[i
].remove
= true;
454 else if (!rb
->strcmp(tidy_types
[selection
].filestring
, "< NONE >"))
456 for (i
=0; i
<tidy_type_count
; i
++)
458 if (tidy_types
[i
].filestring
[0] != '<')
459 tidy_types
[i
].remove
= false;
462 else /* toggle all untill the next <> */
465 while (selection
< tidy_type_count
&&
466 tidy_types
[selection
].filestring
[0] != '<')
468 tidy_types
[selection
].remove
= !tidy_types
[selection
].remove
;
474 tidy_types
[selection
].remove
= !tidy_types
[selection
].remove
;
475 tidy_loaded_and_changed
= true;
476 return ACTION_REDRAW
;
481 enum tidy_return
tidy_lcd_menu(void)
484 enum tidy_return status
= TIDY_RETURN_OK
;
485 bool menu_quit
= false;
487 MENUITEM_STRINGLIST(menu
, "Disktidy Menu", NULL
,
488 "Start Cleaning", "Files to Clean",
493 switch(rb
->do_menu(&menu
, &selection
, NULL
, false))
496 menu_quit
= true; /* start cleaning */
501 bool show_icons
= rb
->global_settings
->show_icons
;
502 struct simplelist_info list
;
503 rb
->simplelist_info_init(&list
, "Files to Clean",
504 tidy_type_count
, NULL
);
505 list
.get_icon
= get_icon
;
506 list
.get_name
= get_name
;
507 list
.action_callback
= list_action_callback
;
508 rb
->simplelist_show_list(&list
);
509 rb
->global_settings
->show_icons
= show_icons
;
514 status
= TIDY_RETURN_ABORT
; /* exit plugin */
522 /* this is the plugin entry point */
523 enum plugin_status
plugin_start(const void* parameter
)
525 enum tidy_return status
;
529 tidy_load_file(DEFAULT_FILES
);
530 tidy_load_file(CUSTOM_FILES
);
531 if (tidy_type_count
== 0)
533 rb
->splash(3*HZ
, "Missing disktidy.config file");
536 status
= tidy_lcd_menu();
537 if (tidy_loaded_and_changed
)
539 int fd
= rb
->creat(CUSTOM_FILES
);
543 for(i
=0;i
<tidy_type_count
;i
++)
545 rb
->fdprintf(fd
, "%s%c: %s\n", tidy_types
[i
].filestring
,
546 tidy_types
[i
].directory
?'/':'\0',
547 tidy_types
[i
].remove
?"yes":"no");
552 if (status
== TIDY_RETURN_ABORT
)
562 case TIDY_RETURN_ERROR
:
564 case TIDY_RETURN_USB
:
565 return PLUGIN_USB_CONNECTED
;
566 case TIDY_RETURN_ABORT
:
571 if (rb
->default_event_handler(rb
->button_get(false)) == SYS_USB_CONNECTED
)
572 return PLUGIN_USB_CONNECTED
;