autodetection: convert path to native separators before displaying it.
[Rockbox.git] / apps / gui / quickscreen.c
blob09592093e742488a4bb047cd0b4b173252d0d111
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Jonathan Gordon
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 #include <stdio.h>
22 #include "config.h"
23 #include "system.h"
24 #include "icons.h"
25 #include "font.h"
26 #include "kernel.h"
27 #include "misc.h"
28 #include "statusbar.h"
29 #include "action.h"
30 #include "settings_list.h"
31 #include "lang.h"
32 #include "playlist.h"
33 #include "dsp.h"
34 #include "viewport.h"
35 #include "audio.h"
36 #include "quickscreen.h"
37 #include "talk.h"
39 static struct viewport vps[NB_SCREENS][QUICKSCREEN_ITEM_COUNT];
40 static struct viewport vp_icons[NB_SCREENS];
41 /* vp_icons will be used like this:
42 the side icons will be aligned to the top of this vp and to their sides
43 the bottom icon wil be aligned center and at the bottom of this vp */
45 #define MIN_LINES 4
46 #define MAX_NEEDED_LINES 8
47 #define CENTER_MARGIN 10 /* pixels between the 2 center items minimum */
48 #define CENTER_ICONAREA_WIDTH (CENTER_MARGIN+8*2)
50 static void quickscreen_fix_viewports(struct gui_quickscreen *qs,
51 struct screen *display,
52 struct viewport *parent)
54 #ifdef HAVE_REMOTE_LCD
55 int screen = display->screen_type;
56 #else
57 const int screen = 0;
58 #endif
60 int char_height, i;
61 int left_width, right_width, bottom_lines = 3;
62 unsigned char *s;
63 int nb_lines = viewport_get_nb_lines(parent);
64 char_height = parent->height/nb_lines;
66 vp_icons[screen] = *parent;
68 vps[screen][QUICKSCREEN_BOTTOM] = *parent;
69 if (nb_lines <= MIN_LINES) /* make the bottom item use 1 line */
70 bottom_lines = 1;
71 else
72 bottom_lines = 2;
73 vps[screen][QUICKSCREEN_BOTTOM].height = bottom_lines*char_height;
74 vps[screen][QUICKSCREEN_BOTTOM].y =
75 parent->y + parent->height - bottom_lines*char_height;
76 if (nb_lines >= MAX_NEEDED_LINES)
78 vps[screen][QUICKSCREEN_BOTTOM].y -= char_height;
81 /* adjust the left/right items widths to fit the screen nicely */
82 s = P2STR(ID2P(qs->items[QUICKSCREEN_LEFT]->lang_id));
83 left_width = display->getstringsize(s, NULL, NULL);
84 s = P2STR(ID2P(qs->items[QUICKSCREEN_RIGHT]->lang_id));
85 right_width = display->getstringsize(s, NULL, NULL);
86 nb_lines -= bottom_lines;
88 vps[screen][QUICKSCREEN_LEFT] = *parent;
89 vps[screen][QUICKSCREEN_RIGHT] = *parent;
90 vps[screen][QUICKSCREEN_LEFT].x = parent->x;
91 if (nb_lines <= MIN_LINES)
92 i = 0;
93 else
94 i = nb_lines/2;
95 vps[screen][QUICKSCREEN_LEFT].y = parent->y + (i*char_height);
96 vps[screen][QUICKSCREEN_RIGHT].y = parent->y + (i*char_height);
97 if (nb_lines >= 3)
98 i = 3*char_height;
99 else
100 i = nb_lines*char_height;
102 vps[screen][QUICKSCREEN_LEFT].height = i;
103 vps[screen][QUICKSCREEN_RIGHT].height = i;
104 vp_icons[screen].y = vps[screen][QUICKSCREEN_LEFT].y + (char_height/2);
105 vp_icons[screen].height =
106 vps[screen][QUICKSCREEN_BOTTOM].y - vp_icons[screen].y;
108 if (left_width + right_width > display->width - CENTER_MARGIN) /* scrolling needed */
110 int width = (parent->width - CENTER_ICONAREA_WIDTH)/2;
111 vps[screen][QUICKSCREEN_LEFT].width = width;
112 vps[screen][QUICKSCREEN_RIGHT].width = width;
113 vps[screen][QUICKSCREEN_RIGHT].x = parent->x+parent->width - width;
114 vp_icons[screen].x = parent->x + width;
115 vp_icons[screen].width = CENTER_ICONAREA_WIDTH;
117 else
119 int width, pad = 0;
120 if (left_width > right_width)
121 width = left_width;
122 else
123 width = right_width;
124 width += CENTER_MARGIN;
125 if (width*2 < parent->width/2)
127 width += parent->width/6;
128 /* add some padding on the edges */
129 pad = CENTER_MARGIN;
131 vps[screen][QUICKSCREEN_LEFT].width = width;
132 vps[screen][QUICKSCREEN_RIGHT].width = width;
133 vps[screen][QUICKSCREEN_RIGHT].x = parent->x + parent->width - width;
134 vp_icons[screen].x = parent->x + width;
135 if (pad)
137 vp_icons[screen].x += pad;
138 vps[screen][QUICKSCREEN_LEFT].x += pad;
139 vps[screen][QUICKSCREEN_RIGHT].x -= pad;
140 /* need to add the pad to the bottom to make it all centered nicely */
141 vps[screen][QUICKSCREEN_BOTTOM].x += pad;
142 vps[screen][QUICKSCREEN_BOTTOM].width -= pad;
144 vp_icons[screen].width = vps[screen][QUICKSCREEN_RIGHT].x - width;
149 static void quickscreen_draw_text(char *s, int item, bool title,
150 struct screen *display, struct viewport *vp)
152 int nb_lines = viewport_get_nb_lines(vp);
153 int w, h, line = 0, x = 0;
154 display->getstringsize(s, &w, &h);
156 if (nb_lines > 1 && !title)
157 line = 1;
158 switch (item)
160 case QUICKSCREEN_BOTTOM:
161 x = (vp->width - w)/2;
162 break;
163 case QUICKSCREEN_LEFT:
164 x = 0;
165 break;
166 case QUICKSCREEN_RIGHT:
167 x = vp->width - w;
168 break;
170 if (w>vp->width)
171 display->puts_scroll(0, line, s);
172 else
173 display->putsxy(x, line*h, s);
176 static void gui_quickscreen_draw(struct gui_quickscreen *qs,
177 struct screen *display,
178 struct viewport *parent)
180 #ifdef HAVE_REMOTE_LCD
181 int screen = display->screen_type;
182 #else
183 const int screen = 0;
184 #endif
186 int i;
187 char buf[MAX_PATH];
188 unsigned char *title, *value;
189 void *setting;
190 int temp;
191 display->set_viewport(parent);
192 display->clear_viewport();
193 for (i=0; i<QUICKSCREEN_ITEM_COUNT; i++)
195 if (!qs->items[i])
196 continue;
197 display->set_viewport(&vps[screen][i]);
198 display->scroll_stop(&vps[screen][i]);
200 title = P2STR(ID2P(qs->items[i]->lang_id));
201 setting = qs->items[i]->setting;
202 if ((qs->items[i]->flags & F_BOOL_SETTING) == F_BOOL_SETTING)
203 temp = *(bool*)setting?1:0;
204 else
205 temp = *(int*)setting;
206 value = option_get_valuestring((struct settings_list*)qs->items[i],
207 buf, MAX_PATH, temp);
209 if (vps[screen][i].height < display->char_height*2)
211 char text[MAX_PATH];
212 snprintf(text, MAX_PATH, "%s: %s", title, value);
213 quickscreen_draw_text(text, i, true, display, &vps[screen][i]);
215 else
217 quickscreen_draw_text(title, i, true, display, &vps[screen][i]);
218 quickscreen_draw_text(value, i, false, display, &vps[screen][i]);
220 display->update_viewport();
222 /* draw the icons */
223 display->set_viewport(&vp_icons[screen]);
224 display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
225 vp_icons[screen].width - 8, 0, 7, 8);
226 display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], 0, 0, 7, 8);
227 display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
228 (vp_icons[screen].width/2) - 4,
229 vp_icons[screen].height - 7, 7, 8);
230 display->update_viewport();
232 display->set_viewport(parent);
233 display->update_viewport();
234 display->set_viewport(NULL);
237 static int option_value(const struct settings_list *setting)
239 if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING)
241 return *(bool*)setting->setting==true?1:0;
243 else
244 return *(int*)setting->setting;
247 static void talk_qs_option(struct settings_list *opt, bool enqueue)
249 if (global_settings.talk_menu) {
250 if(!enqueue)
251 talk_shutup();
252 talk_id(opt->lang_id, true);
253 option_talk_value(opt, option_value(opt), true);
258 * Does the actions associated to the given button if any
259 * - qs : the quickscreen
260 * - button : the key we are going to analyse
261 * returns : true if the button corresponded to an action, false otherwise
263 static bool gui_quickscreen_do_button(struct gui_quickscreen * qs, int button)
265 int item;
266 switch(button)
268 case ACTION_QS_LEFT:
269 item = QUICKSCREEN_LEFT;
270 break;
272 case ACTION_QS_DOWN:
273 case ACTION_QS_DOWNINV:
274 item = QUICKSCREEN_BOTTOM;
275 break;
277 case ACTION_QS_RIGHT:
278 item = QUICKSCREEN_RIGHT;
279 break;
281 default:
282 return false;
284 option_select_next_val((struct settings_list *)qs->items[item], false, true);
285 talk_qs_option((struct settings_list *)qs->items[item], false);
286 return true;
289 bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter)
291 int button, i;
292 struct viewport vp[NB_SCREENS];
293 bool changed = false;
294 /* To quit we need either :
295 * - a second press on the button that made us enter
296 * - an action taken while pressing the enter button,
297 * then release the enter button*/
298 bool can_quit = false;
299 gui_syncstatusbar_draw(&statusbars, true);
300 FOR_NB_SCREENS(i)
302 screens[i].set_viewport(NULL);
303 screens[i].stop_scroll();
304 viewport_set_defaults(&vp[i], i);
305 quickscreen_fix_viewports(qs, &screens[i], &vp[i]);
306 gui_quickscreen_draw(qs, &screens[i], &vp[i]);
308 /* Announce current selection on entering this screen. This is all
309 queued up, but can be interrupted as soon as a setting is
310 changed. */
311 cond_talk_ids(VOICE_QUICKSCREEN);
312 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_LEFT], true);
313 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_BOTTOM], true);
314 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_RIGHT], true);
315 while (true) {
316 button = get_action(CONTEXT_QUICKSCREEN,HZ/5);
317 if(default_event_handler(button) == SYS_USB_CONNECTED)
318 return(true);
319 if(gui_quickscreen_do_button(qs, button))
321 changed = true;
322 can_quit=true;
323 FOR_NB_SCREENS(i)
324 gui_quickscreen_draw(qs, &screens[i], &vp[i]);
325 if (qs->callback)
326 qs->callback(qs);
328 else if(button==button_enter)
329 can_quit=true;
331 if((button == button_enter) && can_quit)
332 break;
334 if(button==ACTION_STD_CANCEL)
335 break;
337 gui_syncstatusbar_draw(&statusbars, false);
339 /* Notify that we're exiting this screen */
340 cond_talk_ids_fq(VOICE_OK);
341 return changed;
344 bool quick_screen_quick(int button_enter)
346 struct gui_quickscreen qs;
347 bool oldshuffle = global_settings.playlist_shuffle;
348 int oldrepeat = global_settings.repeat_mode;
349 qs.items[QUICKSCREEN_LEFT] =
350 find_setting(&global_settings.playlist_shuffle, NULL);
351 qs.items[QUICKSCREEN_RIGHT] =
352 find_setting(&global_settings.repeat_mode, NULL);
353 qs.items[QUICKSCREEN_BOTTOM] =
354 find_setting(&global_settings.dirfilter, NULL);
355 qs.callback = NULL;
356 if (gui_syncquickscreen_run(&qs, button_enter))
358 settings_save();
359 settings_apply(false);
360 /* make sure repeat/shuffle/any other nasty ones get updated */
361 if ( oldrepeat != global_settings.repeat_mode &&
362 (audio_status() & AUDIO_STATUS_PLAY) )
364 audio_flush_and_reload_tracks();
366 if (oldshuffle != global_settings.playlist_shuffle
367 && audio_status() & AUDIO_STATUS_PLAY)
369 #if CONFIG_CODEC == SWCODEC
370 dsp_set_replaygain();
371 #endif
372 if (global_settings.playlist_shuffle)
373 playlist_randomise(NULL, current_tick, true);
374 else
375 playlist_sort(NULL, true);
378 return(0);
381 #ifdef BUTTON_F3
382 bool quick_screen_f3(int button_enter)
384 struct gui_quickscreen qs;
385 qs.items[QUICKSCREEN_LEFT] =
386 find_setting(&global_settings.scrollbar, NULL);
387 qs.items[QUICKSCREEN_RIGHT] =
388 find_setting(&global_settings.statusbar, NULL);
389 qs.items[QUICKSCREEN_BOTTOM] =
390 find_setting(&global_settings.flip_display, NULL);
391 qs.callback = NULL;
392 if (gui_syncquickscreen_run(&qs, button_enter))
394 settings_save();
395 settings_apply(false);
397 return(0);
399 #endif /* BUTTON_F3 */