1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
31 #include "settings_list.h"
37 #include "quickscreen.h"
40 #include "option_select.h"
43 /* 1 top, 1 bottom, 2 on either side, 1 for the icons
44 * if enough space, top and bottom have 2 lines */
46 #define MAX_NEEDED_LINES 10
47 /* pixels between the 2 center items minimum or between text and icons,
48 * and between text and parent boundaries */
50 #define CENTER_ICONAREA_SIZE (MARGIN+8*2)
52 static void quickscreen_fix_viewports(struct gui_quickscreen
*qs
,
53 struct screen
*display
,
54 struct viewport
*parent
,
56 vps
[QUICKSCREEN_ITEM_COUNT
],
57 struct viewport
*vp_icons
)
59 int char_height
, width
, pad
= 0;
60 int left_width
, right_width
, vert_lines
;
62 int nb_lines
= viewport_get_nb_lines(parent
);
64 /* nb_lines only returns the number of fully visible lines, small screens
65 or really large fonts could cause problems with the calculation below.
70 char_height
= parent
->height
/nb_lines
;
72 /* center the icons VP first */
74 vp_icons
->width
= CENTER_ICONAREA_SIZE
; /* abosulte smallest allowed */
75 vp_icons
->x
= parent
->x
;
76 vp_icons
->x
+= (parent
->width
-CENTER_ICONAREA_SIZE
)/2;
79 vps
[QUICKSCREEN_BOTTOM
] = *parent
;
80 vps
[QUICKSCREEN_TOP
] = *parent
;
81 /* depending on the space the top/buttom items use 1 or 2 lines */
82 if (nb_lines
< MIN_LINES
)
86 vps
[QUICKSCREEN_TOP
].y
= parent
->y
;
87 vps
[QUICKSCREEN_TOP
].height
= vps
[QUICKSCREEN_BOTTOM
].height
88 = vert_lines
*char_height
;
89 vps
[QUICKSCREEN_BOTTOM
].y
90 = parent
->y
+ parent
->height
- vps
[QUICKSCREEN_BOTTOM
].height
;
92 /* enough space vertically, so put a nice margin */
93 if (nb_lines
>= MAX_NEEDED_LINES
)
95 vps
[QUICKSCREEN_TOP
].y
+= MARGIN
;
96 vps
[QUICKSCREEN_BOTTOM
].y
-= MARGIN
;
99 vp_icons
->y
= vps
[QUICKSCREEN_TOP
].y
100 + vps
[QUICKSCREEN_TOP
].height
;
101 vp_icons
->height
= parent
->height
- vp_icons
->y
;
102 vp_icons
->height
-= parent
->height
- vps
[QUICKSCREEN_BOTTOM
].y
;
104 /* adjust the left/right items widths to fit the screen nicely */
105 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_LEFT
]->lang_id
));
106 left_width
= display
->getstringsize(s
, NULL
, NULL
);
107 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_RIGHT
]->lang_id
));
108 right_width
= display
->getstringsize(s
, NULL
, NULL
);
110 width
= MAX(left_width
, right_width
);
111 if (width
*2 + vp_icons
->width
> parent
->width
)
112 { /* crop text viewports */
113 width
= (parent
->width
- vp_icons
->width
)/2;
116 { /* add more gap in icons vp */
117 int excess
= parent
->width
- vp_icons
->width
- width
*2;
118 if (excess
> MARGIN
*4)
123 vp_icons
->x
-= excess
/2;
124 vp_icons
->width
+= excess
;
127 vps
[QUICKSCREEN_LEFT
] = *parent
;
128 vps
[QUICKSCREEN_LEFT
].x
= parent
->x
+ pad
;
129 vps
[QUICKSCREEN_LEFT
].width
= width
;
131 vps
[QUICKSCREEN_RIGHT
] = *parent
;
132 vps
[QUICKSCREEN_RIGHT
].x
= parent
->x
+ parent
->width
- width
- pad
;
133 vps
[QUICKSCREEN_RIGHT
].width
= width
;
135 vps
[QUICKSCREEN_LEFT
].height
= vps
[QUICKSCREEN_RIGHT
].height
138 vps
[QUICKSCREEN_LEFT
].y
= vps
[QUICKSCREEN_RIGHT
].y
139 = parent
->y
+ (parent
->height
/2) - char_height
;
141 /* shrink the icons vp by a few pixels if there is room so the arrows
142 aren't drawn right next to the text */
143 if (vp_icons
->width
> CENTER_ICONAREA_SIZE
*2)
145 vp_icons
->width
-= CENTER_ICONAREA_SIZE
*2/3;
146 vp_icons
->x
+= CENTER_ICONAREA_SIZE
*2/6;
148 if (vp_icons
->height
> CENTER_ICONAREA_SIZE
*2)
150 vp_icons
->height
-= CENTER_ICONAREA_SIZE
*2/3;
151 vp_icons
->y
+= CENTER_ICONAREA_SIZE
*2/6;
155 static void quickscreen_draw_text(const char *s
, int item
, bool title
,
156 struct screen
*display
, struct viewport
*vp
)
158 int nb_lines
= viewport_get_nb_lines(vp
);
159 int w
, h
, line
= 0, x
= 0;
160 display
->getstringsize(s
, &w
, &h
);
162 if (nb_lines
> 1 && !title
)
166 case QUICKSCREEN_TOP
:
167 case QUICKSCREEN_BOTTOM
:
168 x
= (vp
->width
- w
)/2;
170 case QUICKSCREEN_LEFT
:
173 case QUICKSCREEN_RIGHT
:
178 display
->puts_scroll(0, line
, s
);
180 display
->putsxy(x
, line
*h
, s
);
183 static void gui_quickscreen_draw(const struct gui_quickscreen
*qs
,
184 struct screen
*display
,
185 struct viewport
*parent
,
186 struct viewport vps
[QUICKSCREEN_ITEM_COUNT
],
187 struct viewport
*vp_icons
)
191 unsigned const char *title
, *value
;
194 display
->set_viewport(parent
);
195 display
->clear_viewport();
196 for (i
=0; i
<QUICKSCREEN_ITEM_COUNT
; i
++)
200 display
->set_viewport(&vps
[i
]);
201 display
->scroll_stop(&vps
[i
]);
203 title
= P2STR(ID2P(qs
->items
[i
]->lang_id
));
204 setting
= qs
->items
[i
]->setting
;
205 temp
= option_value_as_int(qs
->items
[i
]);
206 value
= option_get_valuestring((struct settings_list
*)qs
->items
[i
],
207 buf
, MAX_PATH
, temp
);
209 if (vps
[i
].height
< display
->getcharheight()*2)
212 snprintf(text
, MAX_PATH
, "%s: %s", title
, value
);
213 quickscreen_draw_text(text
, i
, true, display
, &vps
[i
]);
217 quickscreen_draw_text(title
, i
, true, display
, &vps
[i
]);
218 quickscreen_draw_text(value
, i
, false, display
, &vps
[i
]);
220 display
->update_viewport();
223 display
->set_viewport(vp_icons
);
225 display
->mono_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
226 (vp_icons
->width
/2) - 4, 0, 7, 8);
227 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
229 (vp_icons
->height
/2) - 4, 7, 8);
230 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
], 0,
231 (vp_icons
->height
/2) - 4, 7, 8);
233 display
->mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
234 (vp_icons
->width
/2) - 4,
235 vp_icons
->height
- 8, 7, 8);
237 display
->set_viewport(parent
);
238 display
->update_viewport();
239 display
->set_viewport(NULL
);
242 static void talk_qs_option(struct settings_list
*opt
, bool enqueue
)
244 if (global_settings
.talk_menu
) {
247 talk_id(opt
->lang_id
, true);
248 option_talk_value(opt
, option_value_as_int(opt
), true);
253 * Does the actions associated to the given button if any
254 * - qs : the quickscreen
255 * - button : the key we are going to analyse
256 * returns : true if the button corresponded to an action, false otherwise
258 static bool gui_quickscreen_do_button(struct gui_quickscreen
* qs
, int button
)
266 item
= QUICKSCREEN_TOP
;
270 item
= QUICKSCREEN_LEFT
;
274 item
= QUICKSCREEN_BOTTOM
;
277 case ACTION_QS_RIGHT
:
278 item
= QUICKSCREEN_RIGHT
;
284 option_select_next_val((struct settings_list
*)qs
->items
[item
], invert
, true);
285 talk_qs_option((struct settings_list
*)qs
->items
[item
], false);
289 #ifdef HAVE_TOUCHSCREEN
290 static int quickscreen_touchscreen_button(const struct viewport
291 vps
[QUICKSCREEN_ITEM_COUNT
])
294 /* only hitting the text counts, everything else is exit */
295 if (action_get_touchscreen_press(&x
, &y
) != BUTTON_REL
)
297 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_TOP
], x
, y
))
298 return ACTION_QS_TOP
;
299 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_BOTTOM
], x
, y
))
300 return ACTION_QS_DOWN
;
301 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_LEFT
], x
, y
))
302 return ACTION_QS_LEFT
;
303 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_RIGHT
], x
, y
))
304 return ACTION_QS_RIGHT
;
305 return ACTION_STD_CANCEL
;
309 static bool gui_syncquickscreen_run(struct gui_quickscreen
* qs
, int button_enter
)
312 struct viewport parent
[NB_SCREENS
];
313 struct viewport vps
[NB_SCREENS
][QUICKSCREEN_ITEM_COUNT
];
314 struct viewport vp_icons
[NB_SCREENS
];
315 bool changed
= false;
316 /* To quit we need either :
317 * - a second press on the button that made us enter
318 * - an action taken while pressing the enter button,
319 * then release the enter button*/
320 bool can_quit
= false;
323 screens
[i
].set_viewport(NULL
);
324 screens
[i
].stop_scroll();
325 viewport_set_defaults(&parent
[i
], i
);
326 quickscreen_fix_viewports(qs
, &screens
[i
], &parent
[i
], vps
[i
], &vp_icons
[i
]);
327 gui_quickscreen_draw(qs
, &screens
[i
], &parent
[i
], vps
[i
], &vp_icons
[i
]);
329 /* Announce current selection on entering this screen. This is all
330 queued up, but can be interrupted as soon as a setting is
332 cond_talk_ids(VOICE_QUICKSCREEN
);
333 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_TOP
], true);
334 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_LEFT
], true);
335 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_BOTTOM
], true);
336 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_RIGHT
], true);
338 button
= get_action(CONTEXT_QUICKSCREEN
,HZ
/5);
339 #ifdef HAVE_TOUCHSCREEN
340 if (button
== ACTION_TOUCHSCREEN
)
341 button
= quickscreen_touchscreen_button(vps
[SCREEN_MAIN
]);
343 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
345 if(gui_quickscreen_do_button(qs
, button
))
350 gui_quickscreen_draw(qs
, &screens
[i
], &parent
[i
], vps
[i
],&vp_icons
[i
]);
354 else if(button
==button_enter
)
357 if((button
== button_enter
) && can_quit
)
360 if(button
==ACTION_STD_CANCEL
)
363 /* Notify that we're exiting this screen */
364 cond_talk_ids_fq(VOICE_OK
);
366 { /* stop scrolling before exiting */
367 for (j
= 0; j
< QUICKSCREEN_ITEM_COUNT
; j
++)
368 screens
[i
].scroll_stop(&vps
[i
][j
]);
374 static inline const struct settings_list
*get_setting(int gs_value
,
375 const struct settings_list
*defaultval
)
377 if (gs_value
!= -1 && gs_value
< nb_settings
&&
378 is_setting_quickscreenable(&settings
[gs_value
]))
379 return &settings
[gs_value
];
382 bool quick_screen_quick(int button_enter
)
384 struct gui_quickscreen qs
;
385 bool oldshuffle
= global_settings
.playlist_shuffle
;
386 int oldrepeat
= global_settings
.repeat_mode
;
388 qs
.items
[QUICKSCREEN_TOP
] =
389 get_setting(global_settings
.qs_item_top
,
390 find_setting(&global_settings
.party_mode
, NULL
));
391 qs
.items
[QUICKSCREEN_LEFT
] =
392 get_setting(global_settings
.qs_item_left
,
393 find_setting(&global_settings
.playlist_shuffle
, NULL
));
394 qs
.items
[QUICKSCREEN_RIGHT
] =
395 get_setting(global_settings
.qs_item_right
,
396 find_setting(&global_settings
.repeat_mode
, NULL
));
397 qs
.items
[QUICKSCREEN_BOTTOM
] =
398 get_setting(global_settings
.qs_item_bottom
,
399 find_setting(&global_settings
.dirfilter
, NULL
));
402 if (gui_syncquickscreen_run(&qs
, button_enter
))
405 settings_apply(false);
406 /* make sure repeat/shuffle/any other nasty ones get updated */
407 if ( oldrepeat
!= global_settings
.repeat_mode
&&
408 (audio_status() & AUDIO_STATUS_PLAY
) )
410 audio_flush_and_reload_tracks();
412 if (oldshuffle
!= global_settings
.playlist_shuffle
413 && audio_status() & AUDIO_STATUS_PLAY
)
415 #if CONFIG_CODEC == SWCODEC
416 dsp_set_replaygain();
418 if (global_settings
.playlist_shuffle
)
419 playlist_randomise(NULL
, current_tick
, true);
421 playlist_sort(NULL
, true);
428 bool quick_screen_f3(int button_enter
)
430 struct gui_quickscreen qs
;
431 qs
.items
[QUICKSCREEN_LEFT
] =
432 find_setting(&global_settings
.scrollbar
, NULL
);
433 qs
.items
[QUICKSCREEN_RIGHT
] =
434 find_setting(&global_settings
.statusbar
, NULL
);
435 qs
.items
[QUICKSCREEN_BOTTOM
] =
436 find_setting(&global_settings
.flip_display
, NULL
);
438 if (gui_syncquickscreen_run(&qs
, button_enter
))
441 settings_apply(false);
445 #endif /* BUTTON_F3 */
447 /* stuff to make the quickscreen configurable */
448 bool is_setting_quickscreenable(const struct settings_list
*setting
)
450 /* to keep things simple, only settings which have a lang_id set are ok */
451 if (setting
->lang_id
< 0 || (setting
->flags
&F_BANFROMQS
))
453 switch (setting
->flags
&F_T_MASK
)
459 return (setting
->RESERVED
!= NULL
);
465 void set_as_qs_item(const struct settings_list
*setting
,
466 enum quickscreen_item item
)
469 for(i
=0;i
<nb_settings
;i
++)
471 if (&settings
[i
] == setting
)
476 case QUICKSCREEN_TOP
:
477 global_settings
.qs_item_top
= i
;
479 case QUICKSCREEN_LEFT
:
480 global_settings
.qs_item_left
= i
;
482 case QUICKSCREEN_RIGHT
:
483 global_settings
.qs_item_right
= i
;
485 case QUICKSCREEN_BOTTOM
:
486 global_settings
.qs_item_bottom
= i
;
488 default: /* shut the compiler up */