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 ****************************************************************************/
30 #include "statusbar.h"
32 #include "settings_list.h"
38 #include "quickscreen.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 */
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
;
64 int char_height
, i
, width
, pad
= 0;
65 int left_width
, right_width
, bottom_lines
= 2;
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 */
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)
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
)
130 vps
[screen
][QUICKSCREEN_LEFT
].y
= parent
->y
+ (i
*char_height
);
131 vps
[screen
][QUICKSCREEN_RIGHT
].y
= parent
->y
+ (i
*char_height
);
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
)
155 case QUICKSCREEN_BOTTOM
:
156 x
= (vp
->width
- w
)/2;
158 case QUICKSCREEN_LEFT
:
161 case QUICKSCREEN_RIGHT
:
166 display
->puts_scroll(0, line
, s
);
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
;
178 const int screen
= 0;
183 unsigned char *title
, *value
;
186 display
->set_viewport(parent
);
187 display
->clear_viewport();
188 for (i
=0; i
<QUICKSCREEN_ITEM_COUNT
; i
++)
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)
204 snprintf(text
, MAX_PATH
, "%s: %s", title
, value
);
205 quickscreen_draw_text(text
, i
, true, display
, &vps
[screen
][i
]);
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();
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
) {
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
)
252 item
= QUICKSCREEN_LEFT
;
255 case ACTION_QS_DOWNINV
:
256 invert
= true; /* fallthrough */
258 item
= QUICKSCREEN_BOTTOM
;
261 case ACTION_QS_RIGHT
:
262 item
= QUICKSCREEN_RIGHT
;
268 option_select_next_val((struct settings_list
*)qs
->items
[item
], invert
, true);
269 talk_qs_option((struct settings_list
*)qs
->items
[item
], false);
273 bool gui_syncquickscreen_run(struct gui_quickscreen
* qs
, int button_enter
)
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;
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
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);
299 button
= get_action(CONTEXT_QUICKSCREEN
,HZ
/5);
300 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
302 if(gui_quickscreen_do_button(qs
, button
))
307 gui_quickscreen_draw(qs
, &screens
[i
], &vp
[i
]);
311 else if(button
==button_enter
)
314 if((button
== button_enter
) && can_quit
)
317 if(button
==ACTION_STD_CANCEL
)
320 /* Notify that we're exiting this screen */
321 cond_talk_ids_fq(VOICE_OK
);
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
];
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
));
350 if (gui_syncquickscreen_run(&qs
, button_enter
))
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();
366 if (global_settings
.playlist_shuffle
)
367 playlist_randomise(NULL
, current_tick
, true);
369 playlist_sort(NULL
, true);
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
);
386 if (gui_syncquickscreen_run(&qs
, button_enter
))
389 settings_apply(false);
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
))
401 switch (setting
->flags
&F_T_MASK
)
407 return (setting
->RESERVED
!= NULL
);
413 void set_as_qs_item(const struct settings_list
*setting
,
414 enum QUICKSCREEN_ITEM item
)
417 for(i
=0;i
<nb_settings
;i
++)
419 if (&settings
[i
] == setting
)
424 case QUICKSCREEN_LEFT
:
425 global_settings
.qs_item_left
= i
;
427 case QUICKSCREEN_RIGHT
:
428 global_settings
.qs_item_right
= i
;
430 case QUICKSCREEN_BOTTOM
:
431 global_settings
.qs_item_bottom
= i
;
433 default: /* shut the copiler up */