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 "settings_list.h"
36 #include "quickscreen.h"
39 #include "option_select.h"
42 /* 1 top, 1 bottom, 2 on either side, 1 for the icons
43 * if enough space, top and bottom have 2 lines */
45 #define MAX_NEEDED_LINES 10
46 /* pixels between the 2 center items minimum or between text and icons,
47 * and between text and parent boundaries */
49 #define CENTER_ICONAREA_SIZE (MARGIN+8*2)
51 static void quickscreen_fix_viewports(struct gui_quickscreen
*qs
,
52 struct screen
*display
,
53 struct viewport
*parent
,
55 vps
[QUICKSCREEN_ITEM_COUNT
],
56 struct viewport
*vp_icons
)
58 int char_height
, width
, pad
= 0;
59 int left_width
= 0, right_width
= 0, vert_lines
;
61 int nb_lines
= viewport_get_nb_lines(parent
);
63 /* nb_lines only returns the number of fully visible lines, small screens
64 or really large fonts could cause problems with the calculation below.
69 char_height
= parent
->height
/nb_lines
;
71 /* center the icons VP first */
73 vp_icons
->width
= CENTER_ICONAREA_SIZE
; /* abosulte smallest allowed */
74 vp_icons
->x
= parent
->x
;
75 vp_icons
->x
+= (parent
->width
-CENTER_ICONAREA_SIZE
)/2;
77 vps
[QUICKSCREEN_BOTTOM
] = *parent
;
78 vps
[QUICKSCREEN_TOP
] = *parent
;
79 /* depending on the space the top/buttom items use 1 or 2 lines */
80 if (nb_lines
< MIN_LINES
)
84 vps
[QUICKSCREEN_TOP
].y
= parent
->y
;
85 vps
[QUICKSCREEN_TOP
].height
= vps
[QUICKSCREEN_BOTTOM
].height
86 = vert_lines
*char_height
;
87 vps
[QUICKSCREEN_BOTTOM
].y
88 = parent
->y
+ parent
->height
- vps
[QUICKSCREEN_BOTTOM
].height
;
90 /* enough space vertically, so put a nice margin */
91 if (nb_lines
>= MAX_NEEDED_LINES
)
93 vps
[QUICKSCREEN_TOP
].y
+= MARGIN
;
94 vps
[QUICKSCREEN_BOTTOM
].y
-= MARGIN
;
97 vp_icons
->y
= vps
[QUICKSCREEN_TOP
].y
98 + vps
[QUICKSCREEN_TOP
].height
;
99 vp_icons
->height
= vps
[QUICKSCREEN_BOTTOM
].y
- vp_icons
->y
;
101 /* adjust the left/right items widths to fit the screen nicely */
102 if (qs
->items
[QUICKSCREEN_LEFT
])
104 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_LEFT
]->lang_id
));
105 left_width
= display
->getstringsize(s
, NULL
, NULL
);
107 if (qs
->items
[QUICKSCREEN_RIGHT
])
109 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_RIGHT
]->lang_id
));
110 right_width
= display
->getstringsize(s
, NULL
, NULL
);
113 width
= MAX(left_width
, right_width
);
114 if (width
*2 + vp_icons
->width
> parent
->width
)
115 { /* crop text viewports */
116 width
= (parent
->width
- vp_icons
->width
)/2;
119 { /* add more gap in icons vp */
120 int excess
= parent
->width
- vp_icons
->width
- width
*2;
121 if (excess
> MARGIN
*4)
126 vp_icons
->x
-= excess
/2;
127 vp_icons
->width
+= excess
;
130 vps
[QUICKSCREEN_LEFT
] = *parent
;
131 vps
[QUICKSCREEN_LEFT
].x
= parent
->x
+ pad
;
132 vps
[QUICKSCREEN_LEFT
].width
= width
;
134 vps
[QUICKSCREEN_RIGHT
] = *parent
;
135 vps
[QUICKSCREEN_RIGHT
].x
= parent
->x
+ parent
->width
- width
- pad
;
136 vps
[QUICKSCREEN_RIGHT
].width
= width
;
138 vps
[QUICKSCREEN_LEFT
].height
= vps
[QUICKSCREEN_RIGHT
].height
141 vps
[QUICKSCREEN_LEFT
].y
= vps
[QUICKSCREEN_RIGHT
].y
142 = parent
->y
+ (parent
->height
/2) - char_height
;
144 /* shrink the icons vp by a few pixels if there is room so the arrows
145 aren't drawn right next to the text */
146 if (vp_icons
->width
> CENTER_ICONAREA_SIZE
*2)
148 vp_icons
->width
-= CENTER_ICONAREA_SIZE
*2/3;
149 vp_icons
->x
+= CENTER_ICONAREA_SIZE
*2/6;
151 if (vp_icons
->height
> CENTER_ICONAREA_SIZE
*2)
153 vp_icons
->height
-= CENTER_ICONAREA_SIZE
*2/3;
154 vp_icons
->y
+= CENTER_ICONAREA_SIZE
*2/6;
158 vps
[QUICKSCREEN_LEFT
].flags
&= ~VP_FLAG_ALIGNMENT_MASK
; /* left-aligned */
159 vps
[QUICKSCREEN_TOP
].flags
|= VP_FLAG_ALIGN_CENTER
; /* centered */
160 vps
[QUICKSCREEN_BOTTOM
].flags
|= VP_FLAG_ALIGN_CENTER
; /* centered */
161 vps
[QUICKSCREEN_RIGHT
].flags
&= ~VP_FLAG_ALIGNMENT_MASK
;/* right aligned*/
162 vps
[QUICKSCREEN_RIGHT
].flags
|= VP_FLAG_ALIGN_RIGHT
;
165 static void gui_quickscreen_draw(const struct gui_quickscreen
*qs
,
166 struct screen
*display
,
167 struct viewport
*parent
,
168 struct viewport vps
[QUICKSCREEN_ITEM_COUNT
],
169 struct viewport
*vp_icons
)
173 unsigned const char *title
, *value
;
176 display
->set_viewport(parent
);
177 display
->clear_viewport();
179 for (i
= 0; i
< QUICKSCREEN_ITEM_COUNT
; i
++)
181 struct viewport
*vp
= &vps
[i
];
184 display
->set_viewport(vp
);
186 title
= P2STR(ID2P(qs
->items
[i
]->lang_id
));
187 setting
= qs
->items
[i
]->setting
;
188 temp
= option_value_as_int(qs
->items
[i
]);
189 value
= option_get_valuestring(qs
->items
[i
],
190 buf
, MAX_PATH
, temp
);
192 if (viewport_get_nb_lines(vp
) < 2)
195 snprintf(text
, MAX_PATH
, "%s: %s", title
, value
);
196 display
->puts_scroll(0, 0, text
);
200 display
->puts_scroll(0, 0, title
);
201 display
->puts_scroll(0, 1, value
);
205 display
->set_viewport(vp_icons
);
207 if (qs
->items
[QUICKSCREEN_TOP
] != NULL
)
209 display
->mono_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
210 (vp_icons
->width
/2) - 4, 0, 7, 8);
212 if (qs
->items
[QUICKSCREEN_RIGHT
] != NULL
)
214 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
215 vp_icons
->width
- 8, (vp_icons
->height
/2) - 4, 7, 8);
217 if (qs
->items
[QUICKSCREEN_LEFT
] != NULL
)
219 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
220 0, (vp_icons
->height
/2) - 4, 7, 8);
222 if (qs
->items
[QUICKSCREEN_BOTTOM
] != NULL
)
224 display
->mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
225 (vp_icons
->width
/2) - 4, vp_icons
->height
- 8, 7, 8);
228 display
->set_viewport(parent
);
229 display
->update_viewport();
230 display
->set_viewport(NULL
);
233 static void talk_qs_option(const struct settings_list
*opt
, bool enqueue
)
235 if (!global_settings
.talk_menu
|| !opt
)
240 talk_id(opt
->lang_id
, true);
241 option_talk_value(opt
, option_value_as_int(opt
), true);
245 * Does the actions associated to the given button if any
246 * - qs : the quickscreen
247 * - button : the key we are going to analyse
248 * returns : true if the button corresponded to an action, false otherwise
250 static bool gui_quickscreen_do_button(struct gui_quickscreen
* qs
, int button
)
258 item
= QUICKSCREEN_TOP
;
262 item
= QUICKSCREEN_LEFT
;
266 item
= QUICKSCREEN_BOTTOM
;
269 case ACTION_QS_RIGHT
:
270 item
= QUICKSCREEN_RIGHT
;
276 if (qs
->items
[item
] == NULL
)
278 #ifdef ASCENDING_INT_SETTINGS
279 if (((qs
->items
[item
]->flags
& F_INT_SETTING
) == F_INT_SETTING
) &&
280 ( button
== ACTION_QS_DOWN
|| button
== ACTION_QS_TOP
))
285 option_select_next_val(qs
->items
[item
], invert
, true);
286 talk_qs_option(qs
->items
[item
], false);
290 #ifdef HAVE_TOUCHSCREEN
291 static int quickscreen_touchscreen_button(const struct viewport
292 vps
[QUICKSCREEN_ITEM_COUNT
])
295 /* only hitting the text counts, everything else is exit */
296 if (action_get_touchscreen_press(&x
, &y
) != BUTTON_REL
)
298 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_TOP
], x
, y
))
299 return ACTION_QS_TOP
;
300 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_BOTTOM
], x
, y
))
301 return ACTION_QS_DOWN
;
302 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_LEFT
], x
, y
))
303 return ACTION_QS_LEFT
;
304 else if (viewport_point_within_vp(&vps
[QUICKSCREEN_RIGHT
], x
, y
))
305 return ACTION_QS_RIGHT
;
306 return ACTION_STD_CANCEL
;
310 static bool gui_syncquickscreen_run(struct gui_quickscreen
* qs
, int button_enter
)
313 struct viewport parent
[NB_SCREENS
];
314 struct viewport vps
[NB_SCREENS
][QUICKSCREEN_ITEM_COUNT
];
315 struct viewport vp_icons
[NB_SCREENS
];
316 bool changed
= false;
317 /* To quit we need either :
318 * - a second press on the button that made us enter
319 * - an action taken while pressing the enter button,
320 * then release the enter button*/
321 bool can_quit
= false;
324 screens
[i
].set_viewport(NULL
);
325 screens
[i
].stop_scroll();
326 viewportmanager_theme_enable(i
, true, &parent
[i
]);
327 quickscreen_fix_viewports(qs
, &screens
[i
], &parent
[i
], vps
[i
], &vp_icons
[i
]);
328 gui_quickscreen_draw(qs
, &screens
[i
], &parent
[i
], vps
[i
], &vp_icons
[i
]);
330 /* Announce current selection on entering this screen. This is all
331 queued up, but can be interrupted as soon as a setting is
333 cond_talk_ids(VOICE_QUICKSCREEN
);
334 talk_qs_option(qs
->items
[QUICKSCREEN_TOP
], true);
335 talk_qs_option(qs
->items
[QUICKSCREEN_LEFT
], true);
336 talk_qs_option(qs
->items
[QUICKSCREEN_BOTTOM
], true);
337 talk_qs_option(qs
->items
[QUICKSCREEN_RIGHT
], true);
339 button
= get_action(CONTEXT_QUICKSCREEN
, HZ
/5);
340 #ifdef HAVE_TOUCHSCREEN
341 if (button
== ACTION_TOUCHSCREEN
)
342 button
= quickscreen_touchscreen_button(vps
[SCREEN_MAIN
]);
344 if (default_event_handler(button
) == SYS_USB_CONNECTED
)
346 if (gui_quickscreen_do_button(qs
, button
))
351 gui_quickscreen_draw(qs
, &screens
[i
], &parent
[i
],
352 vps
[i
], &vp_icons
[i
]);
356 else if (button
== button_enter
)
359 if ((button
== button_enter
) && can_quit
)
362 if (button
== ACTION_STD_CANCEL
)
365 /* Notify that we're exiting this screen */
366 cond_talk_ids_fq(VOICE_OK
);
368 { /* stop scrolling before exiting */
369 for (j
= 0; j
< QUICKSCREEN_ITEM_COUNT
; j
++)
370 screens
[i
].scroll_stop(&vps
[i
][j
]);
371 viewportmanager_theme_undo(i
, true);
377 static const struct settings_list
*get_setting(int gs_value
,
378 const struct settings_list
*defaultval
)
380 if (gs_value
!= -1 && gs_value
< nb_settings
&&
381 is_setting_quickscreenable(&settings
[gs_value
]))
382 return &settings
[gs_value
];
386 bool quick_screen_quick(int button_enter
)
388 struct gui_quickscreen qs
;
389 bool oldshuffle
= global_settings
.playlist_shuffle
;
390 int oldrepeat
= global_settings
.repeat_mode
;
392 qs
.items
[QUICKSCREEN_TOP
] =
393 get_setting(global_settings
.qs_items
[QUICKSCREEN_TOP
],
394 find_setting(&global_settings
.party_mode
, NULL
));
395 qs
.items
[QUICKSCREEN_LEFT
] =
396 get_setting(global_settings
.qs_items
[QUICKSCREEN_LEFT
],
397 find_setting(&global_settings
.playlist_shuffle
, NULL
));
398 qs
.items
[QUICKSCREEN_RIGHT
] =
399 get_setting(global_settings
.qs_items
[QUICKSCREEN_RIGHT
],
400 find_setting(&global_settings
.repeat_mode
, NULL
));
401 qs
.items
[QUICKSCREEN_BOTTOM
] =
402 get_setting(global_settings
.qs_items
[QUICKSCREEN_BOTTOM
],
403 find_setting(&global_settings
.dirfilter
, NULL
));
406 if (gui_syncquickscreen_run(&qs
, button_enter
))
409 settings_apply(false);
410 /* make sure repeat/shuffle/any other nasty ones get updated */
411 if ( oldrepeat
!= global_settings
.repeat_mode
&&
412 (audio_status() & AUDIO_STATUS_PLAY
) )
414 audio_flush_and_reload_tracks();
416 if (oldshuffle
!= global_settings
.playlist_shuffle
417 && audio_status() & AUDIO_STATUS_PLAY
)
419 #if CONFIG_CODEC == SWCODEC
420 dsp_set_replaygain();
422 if (global_settings
.playlist_shuffle
)
423 playlist_randomise(NULL
, current_tick
, true);
425 playlist_sort(NULL
, true);
432 bool quick_screen_f3(int button_enter
)
434 struct gui_quickscreen qs
;
435 qs
.items
[QUICKSCREEN_TOP
] = NULL
;
436 qs
.items
[QUICKSCREEN_LEFT
] =
437 find_setting(&global_settings
.scrollbar
, NULL
);
438 qs
.items
[QUICKSCREEN_RIGHT
] =
439 find_setting(&global_settings
.statusbar
, NULL
);
440 qs
.items
[QUICKSCREEN_BOTTOM
] =
441 find_setting(&global_settings
.flip_display
, NULL
);
443 if (gui_syncquickscreen_run(&qs
, button_enter
))
446 settings_apply(false);
450 #endif /* BUTTON_F3 */
452 /* stuff to make the quickscreen configurable */
453 bool is_setting_quickscreenable(const struct settings_list
*setting
)
455 /* to keep things simple, only settings which have a lang_id set are ok */
456 if (setting
->lang_id
< 0 || (setting
->flags
&F_BANFROMQS
))
458 switch (setting
->flags
&F_T_MASK
)
464 return (setting
->RESERVED
!= NULL
);
470 void set_as_qs_item(const struct settings_list
*setting
,
471 enum quickscreen_item item
)
474 for (i
= 0; i
< nb_settings
; i
++)
476 if (&settings
[i
] == setting
)
480 global_settings
.qs_items
[item
] = i
;