blob: 2191764ca2242d9a1f67d9d80cc32482929009ea [file] [log] [blame]
Dan Everton58145512006-08-08 10:46:39 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 David Dent
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Dan Everton58145512006-08-08 10:46:39 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "plugin.h"
22
23PLUGIN_HEADER
Steve Bavin65265772008-05-13 09:57:56 +000024static const struct plugin_api* rb;
Jonathan Gordon5b861932008-05-18 07:27:10 +000025MEM_FUNCTION_WRAPPERS(rb)
Dan Everton58145512006-08-08 10:46:39 +000026
27/* function return values */
28enum tidy_return
29{
30 TIDY_RETURN_OK = 0,
31 TIDY_RETURN_ERROR = 1,
32 TIDY_RETURN_USB = 2,
33 TIDY_RETURN_ABORT = 3,
34};
35
Jonathan Gordon5b861932008-05-18 07:27:10 +000036#define MAX_TYPES 64
37struct tidy_type {
38 char filestring[64];
39 bool directory;
40 bool remove;
41} tidy_types[MAX_TYPES];
42int tidy_type_count;
43bool tidy_loaded_and_changed = false;
44
45#define DEFAULT_FILES PLUGIN_APPS_DIR "/disktidy.config"
46#define CUSTOM_FILES PLUGIN_APPS_DIR "/disktidy_custom.config"
47void add_item(const char* name, int index)
Dan Everton58145512006-08-08 10:46:39 +000048{
Jonathan Gordon5b861932008-05-18 07:27:10 +000049 rb->strcpy(tidy_types[index].filestring, name);
50 if (name[rb->strlen(name)-1] == '/')
51 {
52 tidy_types[index].directory = true;
53 tidy_types[index].filestring[rb->strlen(name)-1] = '\0';
54 }
55 else
56 tidy_types[index].directory = false;
57}
58static int find_file_string(const char *file, char *last_group)
59{
60 char temp[MAX_PATH];
61 int i = 0, idx_last_group = -1;
62 bool folder = false;
63 rb->strcpy(temp, file);
64 if (temp[rb->strlen(temp)-1] == '/')
65 {
66 folder = true;
67 temp[rb->strlen(temp)-1] = '\0';
68 }
69 while (i<tidy_type_count)
70 {
71 if (!rb->strcmp(tidy_types[i].filestring, temp) &&
72 folder == tidy_types[i].directory)
73 return i;
74 else if (!rb->strcmp(tidy_types[i].filestring, last_group))
75 idx_last_group = i;
76 i++;
77 }
78 /* not found, so insert it into its group */
79 if (file[0] != '<' && idx_last_group != -1)
80 {
81 for (i=idx_last_group; i<tidy_type_count; i++)
82 {
83 if (tidy_types[i].filestring[0] == '<')
84 {
85 idx_last_group = i;
86 break;
87 }
88 }
89 /* shift items up one */
90 for (i=tidy_type_count;i>idx_last_group;i--)
91 {
92 rb->strcpy(tidy_types[i].filestring, tidy_types[i-1].filestring);
93 tidy_types[i].directory = tidy_types[i-1].directory;
94 tidy_types[i].remove = tidy_types[i-1].remove;
95 }
96 tidy_type_count++;
97 add_item(file, idx_last_group+1);
98 return idx_last_group+1;
99 }
100 return i;
101}
Dan Everton58145512006-08-08 10:46:39 +0000102
Jonathan Gordon5b861932008-05-18 07:27:10 +0000103bool tidy_load_file(const char* file)
104{
105 int fd = rb->open(file, O_RDONLY), i;
106 char buf[MAX_PATH], *str, *remove;
107 char last_group[MAX_PATH] = "";
108 bool new;
109 if (fd < 0)
110 return false;
111 while ((tidy_type_count < MAX_TYPES) &&
112 rb->read_line(fd, buf, MAX_PATH))
113 {
114 if (rb->settings_parseline(buf, &str, &remove))
115 {
116 i = find_file_string(str, last_group);
117 new = (i >= tidy_type_count);
118 if (!rb->strcmp(remove, "yes"))
119 tidy_types[i].remove = true;
120 else tidy_types[i].remove = false;
121 if (new)
122 {
123 i = tidy_type_count;
124 add_item(str, i);
125 tidy_type_count++;
126 }
127 if (str[0] == '<')
128 rb->strcpy(last_group, str);
129 }
130 }
131 rb->close(fd);
132 return true;
133}
Tom Rossfd27a9d2007-01-18 01:38:50 +0000134
Jonathan Gordon5b861932008-05-18 07:27:10 +0000135bool tidy_remove_item(char *item, int attr)
136{
137 int i;
138 char *file;
139 bool ret = false, rem = false;
140 for (i=0; ret == false && i < tidy_type_count; i++)
141 {
142 file = tidy_types[i].filestring;
143 if (file[rb->strlen(file)-1] == '*')
144 {
145 if (!rb->strncmp(file, item, rb->strlen(file)-1))
146 rem = true;
147 }
148 else if (!rb->strcmp(file, item))
149 rem = true;
150 if (rem)
151 {
152 if (!tidy_types[i].remove)
153 return false;
154 if (attr&ATTR_DIRECTORY)
155 ret = tidy_types[i].directory;
156 else ret = true;
157 }
158 }
159 return ret;
160}
Dan Everton58145512006-08-08 10:46:39 +0000161
162void tidy_lcd_status(const char *name, int *removed)
163{
164 char text[24]; /* "Cleaned up nnnnn items" */
165
166 /* display status text */
167 rb->lcd_clear_display();
168 rb->lcd_puts(0, 0, "Working ...");
169 rb->lcd_puts(0, 1, name);
170 rb->snprintf(text, 24, "Cleaned up %d items", *removed);
Tom Rossfd27a9d2007-01-18 01:38:50 +0000171#ifdef HAVE_LCD_BITMAP
Dan Everton58145512006-08-08 10:46:39 +0000172 rb->lcd_puts(0, 2, text);
Tom Rossfd27a9d2007-01-18 01:38:50 +0000173#endif
Jens Arnoldf9b90e92007-04-06 22:55:00 +0000174 rb->lcd_update();
Dan Everton58145512006-08-08 10:46:39 +0000175}
176
177void tidy_get_absolute_path(struct dirent *entry, char *fullname,
178 const char* name)
179{
180 /* gets absolute path using dirent and name */
181 rb->strcpy(fullname, name);
182 if (rb->strlen(name) > 1)
183 {
184 rb->strcat(fullname, "/");
185 }
186 rb->strcat(fullname, entry->d_name);
187}
188
189enum tidy_return tidy_removedir(const char *name, int *removed)
190{
191 /* delete directory */
192 struct dirent *entry;
193 enum tidy_return status = TIDY_RETURN_OK;
194 int button;
195 DIR *dir;
196 char fullname[MAX_PATH];
197
198 /* display status text */
199 tidy_lcd_status(name, removed);
200
201 rb->yield();
202
203 dir = rb->opendir(name);
204 if (dir)
205 {
206 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
207 /* walk directory */
208 {
209 /* check for user input and usb connect */
Jonathan Gordon5b861932008-05-18 07:27:10 +0000210 button = rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
211 if (button == ACTION_STD_CANCEL)
Dan Everton58145512006-08-08 10:46:39 +0000212 {
213 rb->closedir(dir);
214 return TIDY_RETURN_ABORT;
215 }
216 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
Thom Johansen5818bc32008-04-21 20:16:45 +0000217 {
218 rb->closedir(dir);
219 return TIDY_RETURN_USB;
Dan Everton58145512006-08-08 10:46:39 +0000220 }
221
222 rb->yield();
223
224 /* get absolute path */
225 tidy_get_absolute_path(entry, fullname, name);
226
227 if (entry->attribute & ATTR_DIRECTORY)
228 {
229 /* dir ignore "." and ".." */
230 if ((rb->strcmp(entry->d_name, ".") != 0) && \
231 (rb->strcmp(entry->d_name, "..") != 0))
232 {
233 tidy_removedir(fullname, removed);
234 }
235 }
236 else
237 {
238 /* file */
239 *removed += 1;
240 rb->remove(fullname);
241 }
242 }
243 rb->closedir(dir);
244 /* rmdir */
245 *removed += 1;
246 rb->rmdir(name);
247 }
248 else
249 {
250 status = TIDY_RETURN_ERROR;
251 }
252 return status;
253}
254
Jonathan Gordon5b861932008-05-18 07:27:10 +0000255enum tidy_return tidy_clean(const char *name, int *removed)
Dan Everton58145512006-08-08 10:46:39 +0000256{
257 /* deletes junk files and dirs left by system */
258 struct dirent *entry;
259 enum tidy_return status = TIDY_RETURN_OK;
260 int button;
261 int del; /* has the item been deleted */
262 DIR *dir;
263 char fullname[MAX_PATH];
264
265 /* display status text */
266 tidy_lcd_status(name, removed);
267
268 rb->yield();
269
270 dir = rb->opendir(name);
271 if (dir)
272 {
273 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
274 /* walk directory */
275 {
276 /* check for user input and usb connect */
Jonathan Gordon5b861932008-05-18 07:27:10 +0000277 button = rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
278 if (button == ACTION_STD_CANCEL)
Dan Everton58145512006-08-08 10:46:39 +0000279 {
280 rb->closedir(dir);
281 return TIDY_RETURN_ABORT;
282 }
283 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
Thom Johansen5818bc32008-04-21 20:16:45 +0000284 {
285 rb->closedir(dir);
286 return TIDY_RETURN_USB;
Dan Everton58145512006-08-08 10:46:39 +0000287 }
288
289 rb->yield();
290
291 if (entry->attribute & ATTR_DIRECTORY)
292 {
293 /* directory ignore "." and ".." */
294 if ((rb->strcmp(entry->d_name, ".") != 0) && \
295 (rb->strcmp(entry->d_name, "..") != 0))
296 {
297 del = 0;
298
299 /* get absolute path */
300 tidy_get_absolute_path(entry, fullname, name);
301
Jonathan Gordon5b861932008-05-18 07:27:10 +0000302 if (tidy_remove_item(entry->d_name, entry->attribute))
Dan Everton58145512006-08-08 10:46:39 +0000303 {
Jonathan Gordon5b861932008-05-18 07:27:10 +0000304 /* delete dir */
305 tidy_removedir(fullname, removed);
306 del = 1;
Dan Everton58145512006-08-08 10:46:39 +0000307 }
308
309 if (del == 0)
310 {
311 /* dir not deleted so clean it */
Jonathan Gordon5b861932008-05-18 07:27:10 +0000312 status = tidy_clean(fullname, removed);
Dan Everton58145512006-08-08 10:46:39 +0000313 }
314 }
315 }
316 else
317 {
318 /* file */
319 del = 0;
Jonathan Gordon5b861932008-05-18 07:27:10 +0000320 if (tidy_remove_item(entry->d_name, entry->attribute))
Dan Everton58145512006-08-08 10:46:39 +0000321 {
Jonathan Gordon5b861932008-05-18 07:27:10 +0000322 *removed += 1; /* increment removed files counter */
323
324 /* get absolute path */
325 char fullname[MAX_PATH];
326 tidy_get_absolute_path(entry, fullname, name);
327
328 /* delete file */
329 rb->remove(fullname);
330 del = 1;
Dan Everton58145512006-08-08 10:46:39 +0000331 }
Thom Johansen5818bc32008-04-21 20:16:45 +0000332 }
Dan Everton58145512006-08-08 10:46:39 +0000333 }
334 rb->closedir(dir);
335 return status;
336 }
337 else
338 {
339 return TIDY_RETURN_ERROR;
340 }
341}
342
Jonathan Gordon5b861932008-05-18 07:27:10 +0000343enum plugin_status tidy_do(void)
Dan Everton58145512006-08-08 10:46:39 +0000344{
345 /* clean disk and display num of items removed */
346 int removed = 0;
347 enum tidy_return status;
348 char text[24]; /* "Cleaned up nnnnn items" */
349
350#ifdef HAVE_ADJUSTABLE_CPU_FREQ
351 rb->cpu_boost(true);
352#endif
353
Jonathan Gordon5b861932008-05-18 07:27:10 +0000354 status = tidy_clean("/", &removed);
Dan Everton58145512006-08-08 10:46:39 +0000355
356#ifdef HAVE_ADJUSTABLE_CPU_FREQ
357 rb->cpu_boost(false);
358#endif
359
360 if ((status == TIDY_RETURN_OK) || (status == TIDY_RETURN_ABORT))
361 {
362 rb->lcd_clear_display();
363 rb->snprintf(text, 24, "Cleaned up %d items", removed);
364 if (status == TIDY_RETURN_ABORT)
365 {
Jens Arnold4d6374c2007-03-16 21:56:08 +0000366 rb->splash(HZ, "User aborted");
Dan Everton58145512006-08-08 10:46:39 +0000367 rb->lcd_clear_display();
368 }
Jens Arnold4d6374c2007-03-16 21:56:08 +0000369 rb->splash(HZ*2, text);
Dan Everton58145512006-08-08 10:46:39 +0000370 }
371 return status;
372}
373
Jonathan Gordon5b861932008-05-18 07:27:10 +0000374enum themable_icons get_icon(int item, void * data)
375{
376 (void)data;
377 if (tidy_types[item].filestring[0] == '<') /* special type */
378 return Icon_Folder;
379 else if (tidy_types[item].remove)
380 return Icon_Cursor;
381 else
382 return Icon_NOICON;
383}
384
385char * get_name(int selected_item, void * data,
386 char * buffer, size_t buffer_len)
387{
388 (void)data;
389 if (tidy_types[selected_item].directory)
390 {
391 rb->snprintf(buffer, buffer_len, "%s/",
392 tidy_types[selected_item].filestring);
393 return buffer;
394 }
395 return tidy_types[selected_item].filestring;
396}
397
398int list_action_callback(int action, struct gui_synclist *lists)
399{
400 if (action == ACTION_STD_OK)
401 {
402 int selection = rb->gui_synclist_get_sel_pos(lists);
403 if (tidy_types[selection].filestring[0] == '<')
404 {
405 int i;
406 if (!rb->strcmp(tidy_types[selection].filestring, "< ALL >"))
407 {
408 for (i=0; i<tidy_type_count; i++)
409 {
410 if (tidy_types[i].filestring[0] != '<')
411 tidy_types[i].remove = true;
412 }
413 }
414 else if (!rb->strcmp(tidy_types[selection].filestring, "< NONE >"))
415 {
416 for (i=0; i<tidy_type_count; i++)
417 {
418 if (tidy_types[i].filestring[0] != '<')
419 tidy_types[i].remove = false;
420 }
421 }
422 else /* toggle all untill the next <> */
423 {
424 selection++;
425 while (selection < tidy_type_count &&
426 tidy_types[selection].filestring[0] != '<')
427 {
428 tidy_types[selection].remove = !tidy_types[selection].remove;
429 selection++;
430 }
431 }
432 }
433 else
434 tidy_types[selection].remove = !tidy_types[selection].remove;
435 tidy_loaded_and_changed = true;
436 return ACTION_REDRAW;
437 }
438 return action;
439}
440
Tom Rossfd27a9d2007-01-18 01:38:50 +0000441int tidy_lcd_menu(void)
Dan Everton58145512006-08-08 10:46:39 +0000442{
Thom Johansen5818bc32008-04-21 20:16:45 +0000443 int selection, ret = 3;
Tom Rossfa6ed0d2007-01-18 23:37:51 +0000444 bool menu_quit = false;
Dan Everton58145512006-08-08 10:46:39 +0000445
Tom Rossc7f5ccc2007-03-28 07:33:18 +0000446 MENUITEM_STRINGLIST(menu,"Disktidy Menu",NULL,"Start Cleaning",
447 "Files to Clean","Quit");
Tom Rossfd27a9d2007-01-18 01:38:50 +0000448
Tom Rossfa6ed0d2007-01-18 23:37:51 +0000449 while (!menu_quit)
Tom Rossfd27a9d2007-01-18 01:38:50 +0000450 {
Jonathan Gordon5ca15392008-03-26 03:35:24 +0000451 switch(rb->do_menu(&menu, &selection, NULL, false))
Tom Rossfd27a9d2007-01-18 01:38:50 +0000452 {
453
454 case 0:
Tom Rossfa6ed0d2007-01-18 23:37:51 +0000455 menu_quit = true; /* start cleaning */
456 break;
Tom Rossfd27a9d2007-01-18 01:38:50 +0000457
458 case 1:
Jonathan Gordon5b861932008-05-18 07:27:10 +0000459 {
Jonathan Gordon5348f3d2008-05-22 03:39:59 +0000460 bool show_icons = rb->global_settings->show_icons;
Jonathan Gordon5b861932008-05-18 07:27:10 +0000461 struct simplelist_info list;
Jonathan Gordon5348f3d2008-05-22 03:39:59 +0000462 rb->global_settings->show_icons = true; /* force the icons so its readable */
Jonathan Gordon5b861932008-05-18 07:27:10 +0000463 rb->simplelist_info_init(&list, "Files to Clean", tidy_type_count, NULL);
464 list.get_icon = get_icon;
465 list.get_name = get_name;
466 list.action_callback = list_action_callback;
467 rb->simplelist_show_list(&list);
Jonathan Gordon5348f3d2008-05-22 03:39:59 +0000468 rb->global_settings->show_icons = show_icons;
Jonathan Gordon5b861932008-05-18 07:27:10 +0000469 }
470 break;
Tom Rossfd27a9d2007-01-18 01:38:50 +0000471
Tom Rossc7f5ccc2007-03-28 07:33:18 +0000472 default:
Tom Rossfa6ed0d2007-01-18 23:37:51 +0000473 ret = 99; /* exit plugin */
474 menu_quit = true;
475 break;
Tom Rossfd27a9d2007-01-18 01:38:50 +0000476 }
Dan Everton58145512006-08-08 10:46:39 +0000477 }
Tom Rossfa6ed0d2007-01-18 23:37:51 +0000478 return ret;
Dan Everton58145512006-08-08 10:46:39 +0000479}
480
481/* this is the plugin entry point */
Steve Bavin65265772008-05-13 09:57:56 +0000482enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
Dan Everton58145512006-08-08 10:46:39 +0000483{
Dan Everton58145512006-08-08 10:46:39 +0000484 enum tidy_return status;
Jonathan Gordon5b861932008-05-18 07:27:10 +0000485 int ret;
Dan Everton58145512006-08-08 10:46:39 +0000486 (void)parameter;
487
488 rb = api;
Jonathan Gordon5b861932008-05-18 07:27:10 +0000489 tidy_type_count = 0;
490 tidy_load_file(DEFAULT_FILES);
491 tidy_load_file(CUSTOM_FILES);
492 if (tidy_type_count == 0)
Dan Everton58145512006-08-08 10:46:39 +0000493 {
Jonathan Gordon5b861932008-05-18 07:27:10 +0000494 rb->splash(3*HZ, "Missing disktidy.config file");
495 return PLUGIN_ERROR;
Tom Rossfd27a9d2007-01-18 01:38:50 +0000496 }
Jonathan Gordon5b861932008-05-18 07:27:10 +0000497 ret = tidy_lcd_menu();
498 if (tidy_loaded_and_changed)
499 {
500 int fd = rb->creat(CUSTOM_FILES);
501 int i;
502 if (fd >= 0)
503 {
504 for(i=0;i<tidy_type_count;i++)
505 {
506 rb->fdprintf(fd, "%s%c: %s\n", tidy_types[i].filestring,
507 tidy_types[i].directory?'/':'\0',
508 tidy_types[i].remove?"yes":"no");
509 }
510 rb->close(fd);
511 }
512 }
513 if (ret == 99)
514 return PLUGIN_OK;
Tom Ross10dfc062007-01-18 02:28:57 +0000515 while (true)
Tom Rossfd27a9d2007-01-18 01:38:50 +0000516 {
Jonathan Gordon5b861932008-05-18 07:27:10 +0000517 status = tidy_do();
Dan Everton58145512006-08-08 10:46:39 +0000518
519 switch (status)
520 {
521 case TIDY_RETURN_OK:
522 return PLUGIN_OK;
523 case TIDY_RETURN_ERROR:
524 return PLUGIN_ERROR;
525 case TIDY_RETURN_USB:
526 return PLUGIN_USB_CONNECTED;
527 case TIDY_RETURN_ABORT:
528 return PLUGIN_OK;
529 }
Dan Everton58145512006-08-08 10:46:39 +0000530 }
Tom Rossfd27a9d2007-01-18 01:38:50 +0000531
Tom Ross10dfc062007-01-18 02:28:57 +0000532 if (rb->default_event_handler(rb->button_get(false)) == SYS_USB_CONNECTED)
Tom Rossfd27a9d2007-01-18 01:38:50 +0000533 return PLUGIN_USB_CONNECTED;
534
535 rb->yield();
536
Dan Everton58145512006-08-08 10:46:39 +0000537
538 return PLUGIN_OK;
539}