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"
42 static struct viewport vps
[NB_SCREENS
][QUICKSCREEN_ITEM_COUNT
];
43 static struct viewport vp_icons
[NB_SCREENS
];
44 /* vp_icons will be used like this:
45 the side icons will be aligned to the top of this vp and to their sides
46 the bottom icon will be aligned center and at the bottom of this vp */
49 #define MAX_NEEDED_LINES 8
50 #define CENTER_MARGIN 10 /* pixels between the 2 center items minimum */
51 #define CENTER_ICONAREA_WIDTH (CENTER_MARGIN+8*2)
53 static void quickscreen_fix_viewports(struct gui_quickscreen
*qs
,
54 struct screen
*display
,
55 struct viewport
*parent
)
57 #ifdef HAVE_REMOTE_LCD
58 int screen
= display
->screen_type
;
63 int char_height
, i
, width
, pad
= 0;
64 int left_width
, right_width
, bottom_lines
= 2;
66 int nb_lines
= viewport_get_nb_lines(parent
);
68 /* nb_lines only returns the number of fully visible lines, small screens
69 or really large fonts could cause problems with the calculation below.
74 char_height
= parent
->height
/nb_lines
;
76 /* center the icons VP first */
77 vp_icons
[screen
] = *parent
;
78 vp_icons
[screen
].width
= CENTER_ICONAREA_WIDTH
; /* absolute smallest allowed */
79 vp_icons
[screen
].x
= parent
->x
+ (parent
->width
/ 2 - CENTER_ICONAREA_WIDTH
/ 2);
81 vps
[screen
][QUICKSCREEN_BOTTOM
] = *parent
;
82 if (nb_lines
<= MIN_LINES
) /* make the bottom item use 1 line */
86 vps
[screen
][QUICKSCREEN_BOTTOM
].height
= bottom_lines
*char_height
;
87 vps
[screen
][QUICKSCREEN_BOTTOM
].y
=
88 parent
->y
+ parent
->height
- bottom_lines
*char_height
;
89 if (nb_lines
>= MAX_NEEDED_LINES
)
91 vps
[screen
][QUICKSCREEN_BOTTOM
].y
-= char_height
;
94 /* adjust the left/right items widths to fit the screen nicely */
95 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_LEFT
]->lang_id
));
96 left_width
= display
->getstringsize(s
, NULL
, NULL
);
97 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_RIGHT
]->lang_id
));
98 right_width
= display
->getstringsize(s
, NULL
, NULL
);
99 nb_lines
-= bottom_lines
;
101 width
= MAX(left_width
, right_width
);
102 if (width
*2 + vp_icons
[screen
].width
> display
->lcdwidth
)
103 width
= (display
->lcdwidth
- vp_icons
[screen
].width
)/2;
104 else /* add more gap in icons vp */
106 int excess
= display
->lcdwidth
- vp_icons
[screen
].width
- width
*2;
107 if (excess
> CENTER_MARGIN
*4)
110 excess
-= CENTER_MARGIN
*2;
112 vp_icons
[screen
].x
-= excess
/2;
113 vp_icons
[screen
].width
+= excess
;
115 vps
[screen
][QUICKSCREEN_LEFT
] = *parent
;
116 vps
[screen
][QUICKSCREEN_LEFT
].x
= parent
->x
+ pad
;
117 vps
[screen
][QUICKSCREEN_LEFT
].width
= width
;
119 vps
[screen
][QUICKSCREEN_RIGHT
] = *parent
;
120 vps
[screen
][QUICKSCREEN_RIGHT
].x
= parent
->x
+ parent
->width
- width
- pad
;
121 vps
[screen
][QUICKSCREEN_RIGHT
].width
= width
;
123 /* shrink the icons vp by a few pixels if there is room so the arrows
124 aren't drawn right next to the text */
125 if (vp_icons
[screen
].width
> CENTER_ICONAREA_WIDTH
+8)
127 vp_icons
[screen
].width
-= 8;
128 vp_icons
[screen
].x
+= 4;
132 if (nb_lines
<= MIN_LINES
)
136 vps
[screen
][QUICKSCREEN_LEFT
].y
= parent
->y
+ (i
*char_height
);
137 vps
[screen
][QUICKSCREEN_RIGHT
].y
= parent
->y
+ (i
*char_height
);
141 i
= nb_lines
*char_height
;
143 vps
[screen
][QUICKSCREEN_LEFT
].height
= i
;
144 vps
[screen
][QUICKSCREEN_RIGHT
].height
= i
;
145 vp_icons
[screen
].y
= vps
[screen
][QUICKSCREEN_LEFT
].y
+ (char_height
/2);
146 vp_icons
[screen
].height
=
147 vps
[screen
][QUICKSCREEN_BOTTOM
].y
- vp_icons
[screen
].y
;
150 static void quickscreen_draw_text(char *s
, int item
, bool title
,
151 struct screen
*display
, struct viewport
*vp
)
153 int nb_lines
= viewport_get_nb_lines(vp
);
154 int w
, h
, line
= 0, x
= 0;
155 display
->getstringsize(s
, &w
, &h
);
157 if (nb_lines
> 1 && !title
)
161 case QUICKSCREEN_BOTTOM
:
162 x
= (vp
->width
- w
)/2;
164 case QUICKSCREEN_LEFT
:
167 case QUICKSCREEN_RIGHT
:
172 display
->puts_scroll(0, line
, s
);
174 display
->putsxy(x
, line
*h
, s
);
177 static void gui_quickscreen_draw(struct gui_quickscreen
*qs
,
178 struct screen
*display
,
179 struct viewport
*parent
)
181 #ifdef HAVE_REMOTE_LCD
182 int screen
= display
->screen_type
;
184 const int screen
= 0;
189 unsigned char *title
, *value
;
192 display
->set_viewport(parent
);
193 display
->clear_viewport();
194 for (i
=0; i
<QUICKSCREEN_ITEM_COUNT
; i
++)
198 display
->set_viewport(&vps
[screen
][i
]);
199 display
->scroll_stop(&vps
[screen
][i
]);
201 title
= P2STR(ID2P(qs
->items
[i
]->lang_id
));
202 setting
= qs
->items
[i
]->setting
;
203 temp
= option_value_as_int(qs
->items
[i
]);
204 value
= option_get_valuestring((struct settings_list
*)qs
->items
[i
],
205 buf
, MAX_PATH
, temp
);
207 if (vps
[screen
][i
].height
< display
->getcharheight()*2)
210 snprintf(text
, MAX_PATH
, "%s: %s", title
, value
);
211 quickscreen_draw_text(text
, i
, true, display
, &vps
[screen
][i
]);
215 quickscreen_draw_text(title
, i
, true, display
, &vps
[screen
][i
]);
216 quickscreen_draw_text(value
, i
, false, display
, &vps
[screen
][i
]);
218 display
->update_viewport();
221 display
->set_viewport(&vp_icons
[screen
]);
222 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
223 vp_icons
[screen
].width
- 8, 0, 7, 8);
224 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
], 0, 0, 7, 8);
225 display
->mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
226 (vp_icons
[screen
].width
/2) - 4,
227 vp_icons
[screen
].height
- 7, 7, 8);
228 display
->update_viewport();
230 display
->set_viewport(parent
);
231 display
->update_viewport();
232 display
->set_viewport(NULL
);
235 static void talk_qs_option(struct settings_list
*opt
, bool enqueue
)
237 if (global_settings
.talk_menu
) {
240 talk_id(opt
->lang_id
, true);
241 option_talk_value(opt
, option_value_as_int(opt
), true);
246 * Does the actions associated to the given button if any
247 * - qs : the quickscreen
248 * - button : the key we are going to analyse
249 * returns : true if the button corresponded to an action, false otherwise
251 static bool gui_quickscreen_do_button(struct gui_quickscreen
* qs
, int button
)
258 item
= QUICKSCREEN_LEFT
;
261 case ACTION_QS_DOWNINV
:
262 invert
= true; /* fallthrough */
264 item
= QUICKSCREEN_BOTTOM
;
267 case ACTION_QS_RIGHT
:
268 item
= QUICKSCREEN_RIGHT
;
274 option_select_next_val((struct settings_list
*)qs
->items
[item
], invert
, true);
275 talk_qs_option((struct settings_list
*)qs
->items
[item
], false);
278 #ifdef HAVE_TOUCHSCREEN
279 /* figure out which button was pressed...
280 * top is exit, left/right/botton are the respective actions
282 static int quickscreen_touchscreen_button(void)
285 if (action_get_touchscreen_press(&x
, &y
) != BUTTON_REL
)
287 if (y
< vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].y
)
288 return ACTION_STD_CANCEL
;
289 else if (y
> vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].y
+
290 vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].height
)
291 return ACTION_QS_DOWN
;
292 else if (x
< vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].x
+
293 vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].width
)
294 return ACTION_QS_LEFT
;
295 else if (x
>= vps
[SCREEN_MAIN
][QUICKSCREEN_RIGHT
].x
)
296 return ACTION_QS_RIGHT
;
297 return ACTION_STD_CANCEL
;
300 bool gui_syncquickscreen_run(struct gui_quickscreen
* qs
, int button_enter
)
303 struct viewport vp
[NB_SCREENS
];
304 bool changed
= false;
305 /* To quit we need either :
306 * - a second press on the button that made us enter
307 * - an action taken while pressing the enter button,
308 * then release the enter button*/
309 bool can_quit
= false;
312 screens
[i
].set_viewport(NULL
);
313 screens
[i
].stop_scroll();
314 viewport_set_defaults(&vp
[i
], i
);
315 quickscreen_fix_viewports(qs
, &screens
[i
], &vp
[i
]);
316 gui_quickscreen_draw(qs
, &screens
[i
], &vp
[i
]);
318 /* Announce current selection on entering this screen. This is all
319 queued up, but can be interrupted as soon as a setting is
321 cond_talk_ids(VOICE_QUICKSCREEN
);
322 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_LEFT
], true);
323 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_BOTTOM
], true);
324 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_RIGHT
], true);
326 button
= get_action(CONTEXT_QUICKSCREEN
,HZ
/5);
327 #ifdef HAVE_TOUCHSCREEN
328 if (button
== ACTION_TOUCHSCREEN
)
329 button
= quickscreen_touchscreen_button();
331 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
333 if(gui_quickscreen_do_button(qs
, button
))
338 gui_quickscreen_draw(qs
, &screens
[i
], &vp
[i
]);
342 else if(button
==button_enter
)
345 if((button
== button_enter
) && can_quit
)
348 if(button
==ACTION_STD_CANCEL
)
351 /* Notify that we're exiting this screen */
352 cond_talk_ids_fq(VOICE_OK
);
356 static inline const struct settings_list
*get_setting(int gs_value
,
357 const struct settings_list
*defaultval
)
359 if (gs_value
!= -1 && gs_value
< nb_settings
&&
360 is_setting_quickscreenable(&settings
[gs_value
]))
361 return &settings
[gs_value
];
364 bool quick_screen_quick(int button_enter
)
366 struct gui_quickscreen qs
;
367 bool oldshuffle
= global_settings
.playlist_shuffle
;
368 int oldrepeat
= global_settings
.repeat_mode
;
370 qs
.items
[QUICKSCREEN_LEFT
] =
371 get_setting(global_settings
.qs_item_left
,
372 find_setting(&global_settings
.playlist_shuffle
, NULL
));
373 qs
.items
[QUICKSCREEN_RIGHT
] =
374 get_setting(global_settings
.qs_item_right
,
375 find_setting(&global_settings
.repeat_mode
, NULL
));
376 qs
.items
[QUICKSCREEN_BOTTOM
] =
377 get_setting(global_settings
.qs_item_bottom
,
378 find_setting(&global_settings
.dirfilter
, NULL
));
381 if (gui_syncquickscreen_run(&qs
, button_enter
))
384 settings_apply(false);
385 /* make sure repeat/shuffle/any other nasty ones get updated */
386 if ( oldrepeat
!= global_settings
.repeat_mode
&&
387 (audio_status() & AUDIO_STATUS_PLAY
) )
389 audio_flush_and_reload_tracks();
391 if (oldshuffle
!= global_settings
.playlist_shuffle
392 && audio_status() & AUDIO_STATUS_PLAY
)
394 #if CONFIG_CODEC == SWCODEC
395 dsp_set_replaygain();
397 if (global_settings
.playlist_shuffle
)
398 playlist_randomise(NULL
, current_tick
, true);
400 playlist_sort(NULL
, true);
407 bool quick_screen_f3(int button_enter
)
409 struct gui_quickscreen qs
;
410 qs
.items
[QUICKSCREEN_LEFT
] =
411 find_setting(&global_settings
.scrollbar
, NULL
);
412 qs
.items
[QUICKSCREEN_RIGHT
] =
413 find_setting(&global_settings
.statusbar
, NULL
);
414 qs
.items
[QUICKSCREEN_BOTTOM
] =
415 find_setting(&global_settings
.flip_display
, NULL
);
417 if (gui_syncquickscreen_run(&qs
, button_enter
))
420 settings_apply(false);
424 #endif /* BUTTON_F3 */
426 /* stuff to make the quickscreen configurable */
427 bool is_setting_quickscreenable(const struct settings_list
*setting
)
429 /* to keep things simple, only settings which have a lang_id set are ok */
430 if (setting
->lang_id
< 0 || (setting
->flags
&F_BANFROMQS
))
432 switch (setting
->flags
&F_T_MASK
)
438 return (setting
->RESERVED
!= NULL
);
444 void set_as_qs_item(const struct settings_list
*setting
,
445 enum QUICKSCREEN_ITEM item
)
448 for(i
=0;i
<nb_settings
;i
++)
450 if (&settings
[i
] == setting
)
455 case QUICKSCREEN_LEFT
:
456 global_settings
.qs_item_left
= i
;
458 case QUICKSCREEN_RIGHT
:
459 global_settings
.qs_item_right
= i
;
461 case QUICKSCREEN_BOTTOM
:
462 global_settings
.qs_item_bottom
= i
;
464 default: /* shut the copiler up */