1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 Bryan Childs
11 * Copyright (c) 2007 Alexander Levin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #include "shortcuts.h"
27 enum sc_list_action_type
36 static char *link_filename
;
37 static bool user_file
;
38 static int gselected_item
;
39 static bool usb_connected
= false;
41 enum sc_list_action_type
draw_sc_list(struct gui_synclist gui_sc
);
43 /* Will be passed sc_file* as data */
44 char* build_sc_list(int selected_item
, void *data
,
45 char *buffer
, size_t buffer_len
);
47 /* Returns true iff we should leave the main loop */
48 bool list_sc(bool is_editable
);
50 bool goto_entry(char *file_or_dir
);
51 bool ends_with(char *str
, char *suffix
);
54 enum sc_list_action_type
draw_sc_list(struct gui_synclist gui_sc
)
58 rb
->gui_synclist_draw(&gui_sc
);
61 /* draw the statusbar, should be done often */
62 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
64 button
= rb
->get_action(CONTEXT_LIST
, TIMEOUT_BLOCK
);
65 if (rb
->gui_synclist_do_button(&gui_sc
, &button
,
66 LIST_WRAP_UNLESS_HELD
)) {
67 /* automatic handling of user input.
68 * _UNLESS_HELD can be _ON or _OFF also
69 * selection changed, so redraw */
72 switch (button
) { /* process the user input */
74 gselected_item
= rb
->gui_synclist_get_sel_pos(&gui_sc
);
77 /* Only allow delete entries in the default file
78 * since entries can be appended (with a plugin)
79 * to the default file only. The behaviour is thus
80 * symmetric in this respect. */
82 gselected_item
= rb
->gui_synclist_get_sel_pos(&gui_sc
);
86 case ACTION_STD_CANCEL
:
89 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
97 char* build_sc_list(int selected_item
, void *data
,
98 char *buffer
, size_t buffer_len
)
100 sc_file_t
*file
= (sc_file_t
*)data
;
102 if (!is_valid_index(file
, selected_item
)) {
105 sc_entry_t
*entry
= file
->entries
+ selected_item
;
106 rb
->snprintf(buffer
, buffer_len
, "%s", entry
->disp
);
111 bool list_sc(bool is_editable
)
113 int selected_item
= 0;
114 char selected_dir
[MAX_PATH
];
115 enum sc_list_action_type action
= SCLA_NONE
;
116 struct gui_synclist gui_sc
;
118 rb
->memset(selected_dir
, 0, sizeof(selected_dir
));
120 /* Setup the GUI list object, draw it to the screen,
121 * and then handle the user input to it */
122 rb
->gui_synclist_init(&gui_sc
, &build_sc_list
, &sc_file
, false, 1, NULL
);
123 rb
->gui_synclist_set_title(&gui_sc
,
124 (is_editable
?"Shortcuts (editable)":"Shortcuts (sealed)"), NOICON
);
125 rb
->gui_synclist_set_nb_items(&gui_sc
, sc_file
.entry_cnt
);
126 rb
->gui_synclist_limit_scroll(&gui_sc
, false);
127 rb
->gui_synclist_select_item(&gui_sc
, 0);
129 /* Draw the prepared widget to the LCD now */
130 action
= draw_sc_list(gui_sc
);
131 if (action
== SCLA_USB
) {
132 usb_connected
= true;
136 /* which item do we action? */
137 selected_item
= gselected_item
;
139 if (!is_valid_index(&sc_file
, selected_item
)) {
140 /* This should never happen */
141 rb
->splash(HZ
*2, "Bad entry selected!");
145 /* perform the following actions if the user "selected"
146 * the item in the list (i.e. they want to go there
147 * in the filebrowser tree */
150 return goto_entry(sc_file
.entries
[selected_item
].path
);
152 rb
->splashf(HZ
, "Deleting %s", sc_file
.entries
[selected_item
].disp
);
153 remove_entry(&sc_file
, selected_item
);
154 dump_sc_file(&sc_file
, link_filename
);
155 return (sc_file
.entry_cnt
== 0);
162 bool goto_entry(char *file_or_dir
)
164 DEBUGF("Trying to go to '%s'...\n", file_or_dir
);
166 bool is_dir
= ends_with(file_or_dir
, PATH_SEPARATOR
);
171 exists
= rb
->dir_exists(file_or_dir
);
174 exists
= rb
->file_exists(file_or_dir
);
178 rb
->splashf(HZ
*2, "%s %s no longer exists on disk", what
, file_or_dir
);
181 /* Set the browsers dirfilter to the global setting
182 * This is required in case the plugin was launched
183 * from the plugins browser, in which case the
184 * dirfilter is set to only display .rock files */
185 rb
->set_dirfilter(rb
->global_settings
->dirfilter
);
187 /* Change directory to the entry selected by the user */
188 rb
->set_current_file(file_or_dir
);
193 bool ends_with(char *string
, char *suffix
)
195 unsigned int str_len
= rb
->strlen(string
);
196 unsigned int sfx_len
= rb
->strlen(suffix
);
197 if (str_len
< sfx_len
)
199 return (rb
->strncmp(string
+ str_len
- sfx_len
, suffix
, sfx_len
) == 0);
203 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* void_parameter
)
208 /* This is a viewer, so a parameter must have been specified */
209 if (void_parameter
== NULL
) {
210 rb
->splash(HZ
*2, "No parameter specified!");
213 link_filename
= (char*)void_parameter
;
214 user_file
= (rb
->strcmp(link_filename
, SHORTCUTS_FILENAME
) != 0);
216 allocate_memory(&memory_buf
, &memory_bufsize
);
218 if (!load_sc_file(&sc_file
, link_filename
, true,
219 memory_buf
, memory_bufsize
)) {
220 DEBUGF("Could not load %s\n", link_filename
);
223 if (sc_file
.entry_cnt
==0) {
224 rb
->splash(HZ
*2, "No shortcuts in the file!");
226 } else if ((sc_file
.entry_cnt
==1) && user_file
) {
227 /* if there's only one entry in the user .link file,
228 * go straight to it without displaying the menu
229 * thus allowing 'quick links' */
230 goto_entry(sc_file
.entries
[0].path
);
235 /* Display a menu to choose between the entries */
236 leave_loop
= list_sc(!user_file
);
237 } while (!leave_loop
);
239 return usb_connected
? PLUGIN_USB_CONNECTED
: PLUGIN_OK
;