Fix typos in comments
[kugel-rb/myfork.git] / apps / gui / quickscreen.c
blob1ddae2390a575e2fc5d2c46a774f479d9f26889e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Jonathan Gordon
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 ****************************************************************************/
23 #include <stdio.h>
24 #include "config.h"
25 #include "system.h"
26 #include "icons.h"
27 #include "font.h"
28 #include "kernel.h"
29 #include "misc.h"
30 #include "statusbar.h"
31 #include "action.h"
32 #include "settings_list.h"
33 #include "lang.h"
34 #include "playlist.h"
35 #include "dsp.h"
36 #include "viewport.h"
37 #include "audio.h"
38 #include "quickscreen.h"
39 #include "talk.h"
40 #include "list.h"
41 #include "option_select.h"
43 static struct viewport vps[NB_SCREENS][QUICKSCREEN_ITEM_COUNT];
44 static struct viewport vp_icons[NB_SCREENS];
45 /* vp_icons will be used like this:
46 the side icons will be aligned to the top of this vp and to their sides
47 the bottom icon will be aligned center and at the bottom of this vp */
49 #define MIN_LINES 4
50 #define MAX_NEEDED_LINES 8
51 #define CENTER_MARGIN 10 /* pixels between the 2 center items minimum */
52 #define CENTER_ICONAREA_WIDTH (CENTER_MARGIN+8*2)
54 static void quickscreen_fix_viewports(struct gui_quickscreen *qs,
55 struct screen *display,
56 struct viewport *parent)
58 #ifdef HAVE_REMOTE_LCD
59 int screen = display->screen_type;
60 #else
61 const int screen = 0;
62 #endif
64 int char_height, i, width, pad = 0;
65 int left_width, right_width, bottom_lines = 2;
66 unsigned char *s;
67 int nb_lines = viewport_get_nb_lines(parent);
68 char_height = parent->height/nb_lines;
70 /* center the icons VP first */
71 vp_icons[screen] = *parent;
72 vp_icons[screen].width = CENTER_ICONAREA_WIDTH; /* absolute smallest allowed */
73 vp_icons[screen].x = parent->x + (parent->width / 2 - CENTER_ICONAREA_WIDTH / 2);
75 vps[screen][QUICKSCREEN_BOTTOM] = *parent;
76 if (nb_lines <= MIN_LINES) /* make the bottom item use 1 line */
77 bottom_lines = 1;
78 else
79 bottom_lines = 2;
80 vps[screen][QUICKSCREEN_BOTTOM].height = bottom_lines*char_height;
81 vps[screen][QUICKSCREEN_BOTTOM].y =
82 parent->y + parent->height - bottom_lines*char_height;
83 if (nb_lines >= MAX_NEEDED_LINES)
85 vps[screen][QUICKSCREEN_BOTTOM].y -= char_height;
88 /* adjust the left/right items widths to fit the screen nicely */
89 s = P2STR(ID2P(qs->items[QUICKSCREEN_LEFT]->lang_id));
90 left_width = display->getstringsize(s, NULL, NULL);
91 s = P2STR(ID2P(qs->items[QUICKSCREEN_RIGHT]->lang_id));
92 right_width = display->getstringsize(s, NULL, NULL);
93 nb_lines -= bottom_lines;
95 width = MAX(left_width, right_width);
96 if (width*2 + vp_icons[screen].width > display->lcdwidth)
97 width = (display->lcdwidth - vp_icons[screen].width)/2;
98 else /* add more gap in icons vp */
100 int excess = display->lcdwidth - vp_icons[screen].width - width*2;
101 if (excess > CENTER_MARGIN*4)
103 pad = CENTER_MARGIN;
104 excess -= CENTER_MARGIN*2;
106 vp_icons[screen].x -= excess/2;
107 vp_icons[screen].width += excess;
109 vps[screen][QUICKSCREEN_LEFT] = *parent;
110 vps[screen][QUICKSCREEN_LEFT].x = parent->x + pad;
111 vps[screen][QUICKSCREEN_LEFT].width = width;
113 vps[screen][QUICKSCREEN_RIGHT] = *parent;
114 vps[screen][QUICKSCREEN_RIGHT].x = parent->x + parent->width - width - pad;
115 vps[screen][QUICKSCREEN_RIGHT].width = width;
117 /* shrink the icons vp by a few pixels if there is room so the arrows
118 aren't drawn right next to the text */
119 if (vp_icons[screen].width > CENTER_ICONAREA_WIDTH+8)
121 vp_icons[screen].width -= 8;
122 vp_icons[screen].x += 4;
126 if (nb_lines <= MIN_LINES)
127 i = 0;
128 else
129 i = nb_lines/2;
130 vps[screen][QUICKSCREEN_LEFT].y = parent->y + (i*char_height);
131 vps[screen][QUICKSCREEN_RIGHT].y = parent->y + (i*char_height);
132 if (nb_lines >= 3)
133 i = 3*char_height;
134 else
135 i = nb_lines*char_height;
137 vps[screen][QUICKSCREEN_LEFT].height = i;
138 vps[screen][QUICKSCREEN_RIGHT].height = i;
139 vp_icons[screen].y = vps[screen][QUICKSCREEN_LEFT].y + (char_height/2);
140 vp_icons[screen].height =
141 vps[screen][QUICKSCREEN_BOTTOM].y - vp_icons[screen].y;
144 static void quickscreen_draw_text(char *s, int item, bool title,
145 struct screen *display, struct viewport *vp)
147 int nb_lines = viewport_get_nb_lines(vp);
148 int w, h, line = 0, x = 0;
149 display->getstringsize(s, &w, &h);
151 if (nb_lines > 1 && !title)
152 line = 1;
153 switch (item)
155 case QUICKSCREEN_BOTTOM:
156 x = (vp->width - w)/2;
157 break;
158 case QUICKSCREEN_LEFT:
159 x = 0;
160 break;
161 case QUICKSCREEN_RIGHT:
162 x = vp->width - w;
163 break;
165 if (w>vp->width)
166 display->puts_scroll(0, line, s);
167 else
168 display->putsxy(x, line*h, s);
171 static void gui_quickscreen_draw(struct gui_quickscreen *qs,
172 struct screen *display,
173 struct viewport *parent)
175 #ifdef HAVE_REMOTE_LCD
176 int screen = display->screen_type;
177 #else
178 const int screen = 0;
179 #endif
181 int i;
182 char buf[MAX_PATH];
183 unsigned char *title, *value;
184 void *setting;
185 int temp;
186 display->set_viewport(parent);
187 display->clear_viewport();
188 for (i=0; i<QUICKSCREEN_ITEM_COUNT; i++)
190 if (!qs->items[i])
191 continue;
192 display->set_viewport(&vps[screen][i]);
193 display->scroll_stop(&vps[screen][i]);
195 title = P2STR(ID2P(qs->items[i]->lang_id));
196 setting = qs->items[i]->setting;
197 temp = option_value_as_int(qs->items[i]);
198 value = option_get_valuestring((struct settings_list*)qs->items[i],
199 buf, MAX_PATH, temp);
201 if (vps[screen][i].height < display->getcharheight()*2)
203 char text[MAX_PATH];
204 snprintf(text, MAX_PATH, "%s: %s", title, value);
205 quickscreen_draw_text(text, i, true, display, &vps[screen][i]);
207 else
209 quickscreen_draw_text(title, i, true, display, &vps[screen][i]);
210 quickscreen_draw_text(value, i, false, display, &vps[screen][i]);
212 display->update_viewport();
214 /* draw the icons */
215 display->set_viewport(&vp_icons[screen]);
216 display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
217 vp_icons[screen].width - 8, 0, 7, 8);
218 display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], 0, 0, 7, 8);
219 display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
220 (vp_icons[screen].width/2) - 4,
221 vp_icons[screen].height - 7, 7, 8);
222 display->update_viewport();
224 display->set_viewport(parent);
225 display->update_viewport();
226 display->set_viewport(NULL);
229 static void talk_qs_option(struct settings_list *opt, bool enqueue)
231 if (global_settings.talk_menu) {
232 if(!enqueue)
233 talk_shutup();
234 talk_id(opt->lang_id, true);
235 option_talk_value(opt, option_value_as_int(opt), true);
240 * Does the actions associated to the given button if any
241 * - qs : the quickscreen
242 * - button : the key we are going to analyse
243 * returns : true if the button corresponded to an action, false otherwise
245 static bool gui_quickscreen_do_button(struct gui_quickscreen * qs, int button)
247 int item;
248 bool invert = false;
249 switch(button)
251 case ACTION_QS_LEFT:
252 item = QUICKSCREEN_LEFT;
253 break;
255 case ACTION_QS_DOWNINV:
256 invert = true; /* fallthrough */
257 case ACTION_QS_DOWN:
258 item = QUICKSCREEN_BOTTOM;
259 break;
261 case ACTION_QS_RIGHT:
262 item = QUICKSCREEN_RIGHT;
263 break;
265 default:
266 return false;
268 option_select_next_val((struct settings_list *)qs->items[item], invert, true);
269 talk_qs_option((struct settings_list *)qs->items[item], false);
270 return true;
273 bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter)
275 int button, i;
276 struct viewport vp[NB_SCREENS];
277 bool changed = false;
278 /* To quit we need either :
279 * - a second press on the button that made us enter
280 * - an action taken while pressing the enter button,
281 * then release the enter button*/
282 bool can_quit = false;
283 FOR_NB_SCREENS(i)
285 screens[i].set_viewport(NULL);
286 screens[i].stop_scroll();
287 viewport_set_defaults(&vp[i], i);
288 quickscreen_fix_viewports(qs, &screens[i], &vp[i]);
289 gui_quickscreen_draw(qs, &screens[i], &vp[i]);
291 /* Announce current selection on entering this screen. This is all
292 queued up, but can be interrupted as soon as a setting is
293 changed. */
294 cond_talk_ids(VOICE_QUICKSCREEN);
295 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_LEFT], true);
296 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_BOTTOM], true);
297 talk_qs_option((struct settings_list *)qs->items[QUICKSCREEN_RIGHT], true);
298 while (true) {
299 button = get_action(CONTEXT_QUICKSCREEN,HZ/5);
300 if(default_event_handler(button) == SYS_USB_CONNECTED)
301 return(true);
302 if(gui_quickscreen_do_button(qs, button))
304 changed = true;
305 can_quit=true;
306 FOR_NB_SCREENS(i)
307 gui_quickscreen_draw(qs, &screens[i], &vp[i]);
308 if (qs->callback)
309 qs->callback(qs);
311 else if(button==button_enter)
312 can_quit=true;
314 if((button == button_enter) && can_quit)
315 break;
317 if(button==ACTION_STD_CANCEL)
318 break;
320 /* Notify that we're exiting this screen */
321 cond_talk_ids_fq(VOICE_OK);
322 return changed;
325 static inline const struct settings_list *get_setting(int gs_value,
326 const struct settings_list *defaultval)
328 if (gs_value != -1 && gs_value < nb_settings &&
329 is_setting_quickscreenable(&settings[gs_value]))
330 return &settings[gs_value];
331 return defaultval;
333 bool quick_screen_quick(int button_enter)
335 struct gui_quickscreen qs;
336 bool oldshuffle = global_settings.playlist_shuffle;
337 int oldrepeat = global_settings.repeat_mode;
339 qs.items[QUICKSCREEN_LEFT] =
340 get_setting(global_settings.qs_item_left,
341 find_setting(&global_settings.playlist_shuffle, NULL));
342 qs.items[QUICKSCREEN_RIGHT] =
343 get_setting(global_settings.qs_item_right,
344 find_setting(&global_settings.repeat_mode, NULL));
345 qs.items[QUICKSCREEN_BOTTOM] =
346 get_setting(global_settings.qs_item_bottom,
347 find_setting(&global_settings.dirfilter, NULL));
349 qs.callback = NULL;
350 if (gui_syncquickscreen_run(&qs, button_enter))
352 settings_save();
353 settings_apply(false);
354 /* make sure repeat/shuffle/any other nasty ones get updated */
355 if ( oldrepeat != global_settings.repeat_mode &&
356 (audio_status() & AUDIO_STATUS_PLAY) )
358 audio_flush_and_reload_tracks();
360 if (oldshuffle != global_settings.playlist_shuffle
361 && audio_status() & AUDIO_STATUS_PLAY)
363 #if CONFIG_CODEC == SWCODEC
364 dsp_set_replaygain();
365 #endif
366 if (global_settings.playlist_shuffle)
367 playlist_randomise(NULL, current_tick, true);
368 else
369 playlist_sort(NULL, true);
372 return(0);
375 #ifdef BUTTON_F3
376 bool quick_screen_f3(int button_enter)
378 struct gui_quickscreen qs;
379 qs.items[QUICKSCREEN_LEFT] =
380 find_setting(&global_settings.scrollbar, NULL);
381 qs.items[QUICKSCREEN_RIGHT] =
382 find_setting(&global_settings.statusbar, NULL);
383 qs.items[QUICKSCREEN_BOTTOM] =
384 find_setting(&global_settings.flip_display, NULL);
385 qs.callback = NULL;
386 if (gui_syncquickscreen_run(&qs, button_enter))
388 settings_save();
389 settings_apply(false);
391 return(0);
393 #endif /* BUTTON_F3 */
395 /* stuff to make the quickscreen configurable */
396 bool is_setting_quickscreenable(const struct settings_list *setting)
398 /* to keep things simple, only settings which have a lang_id set are ok */
399 if (setting->lang_id < 0 || (setting->flags&F_BANFROMQS))
400 return false;
401 switch (setting->flags&F_T_MASK)
403 case F_T_BOOL:
404 return true;
405 case F_T_INT:
406 case F_T_UINT:
407 return (setting->RESERVED != NULL);
408 default:
409 return false;
413 void set_as_qs_item(const struct settings_list *setting,
414 enum QUICKSCREEN_ITEM item)
416 int i;
417 for(i=0;i<nb_settings;i++)
419 if (&settings[i] == setting)
420 break;
422 switch (item)
424 case QUICKSCREEN_LEFT:
425 global_settings.qs_item_left = i;
426 break;
427 case QUICKSCREEN_RIGHT:
428 global_settings.qs_item_right = i;
429 break;
430 case QUICKSCREEN_BOTTOM:
431 global_settings.qs_item_bottom = i;
432 break;
433 default: /* shut the copiler up */
434 break;