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 static struct viewport vps
[NB_SCREENS
][QUICKSCREEN_ITEM_COUNT
];
44 static struct viewport vp_icons
[NB_SCREENS
];
45 /* 1 top, 1 bottom, 2 on either side, 1 for the icons
46 * if enough space, top and bottom have 2 lines */
48 #define MAX_NEEDED_LINES 10
49 /* pixels between the 2 center items minimum or between text and icons,
50 * and between text and parent boundaries */
52 #define CENTER_ICONAREA_SIZE (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
;
63 int char_height
, width
, pad
= 0;
64 int left_width
, right_width
, vert_lines
;
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_SIZE
; /* abosulte smallest allowed */
79 vp_icons
[screen
].x
= parent
->x
;
80 vp_icons
[screen
].x
+= (parent
->width
-CENTER_ICONAREA_SIZE
)/2;
83 vps
[screen
][QUICKSCREEN_BOTTOM
] = *parent
;
84 vps
[screen
][QUICKSCREEN_TOP
] = *parent
;
85 /* depending on the space the top/buttom items use 1 or 2 lines */
86 if (nb_lines
< MIN_LINES
)
90 vps
[screen
][QUICKSCREEN_TOP
].y
= parent
->y
;
91 vps
[screen
][QUICKSCREEN_TOP
].height
= vps
[screen
][QUICKSCREEN_BOTTOM
].height
92 = vert_lines
*char_height
;
93 vps
[screen
][QUICKSCREEN_BOTTOM
].y
94 = parent
->y
+ parent
->height
- vps
[screen
][QUICKSCREEN_BOTTOM
].height
;
96 /* enough space vertically, so put a nice margin */
97 if (nb_lines
>= MAX_NEEDED_LINES
)
99 vps
[screen
][QUICKSCREEN_TOP
].y
+= MARGIN
;
100 vps
[screen
][QUICKSCREEN_BOTTOM
].y
-= MARGIN
;
103 vp_icons
[screen
].y
= vps
[screen
][QUICKSCREEN_TOP
].y
104 + vps
[screen
][QUICKSCREEN_TOP
].height
;
105 vp_icons
[screen
].height
= parent
->height
- vp_icons
[screen
].y
;
106 vp_icons
[screen
].height
-= parent
->height
- vps
[screen
][QUICKSCREEN_BOTTOM
].y
;
108 /* adjust the left/right items widths to fit the screen nicely */
109 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_LEFT
]->lang_id
));
110 left_width
= display
->getstringsize(s
, NULL
, NULL
);
111 s
= P2STR(ID2P(qs
->items
[QUICKSCREEN_RIGHT
]->lang_id
));
112 right_width
= display
->getstringsize(s
, NULL
, NULL
);
114 width
= MAX(left_width
, right_width
);
115 if (width
*2 + vp_icons
[screen
].width
> display
->lcdwidth
)
116 width
= (display
->lcdwidth
- vp_icons
[screen
].width
)/2;
117 else /* add more gap in icons vp */
119 int excess
= display
->lcdwidth
- vp_icons
[screen
].width
- width
*2;
120 if (excess
> MARGIN
*4)
125 vp_icons
[screen
].x
-= excess
/2;
126 vp_icons
[screen
].width
+= excess
;
129 vps
[screen
][QUICKSCREEN_LEFT
] = *parent
;
130 vps
[screen
][QUICKSCREEN_LEFT
].x
= parent
->x
+ pad
;
131 vps
[screen
][QUICKSCREEN_LEFT
].width
= width
;
133 vps
[screen
][QUICKSCREEN_RIGHT
] = *parent
;
134 vps
[screen
][QUICKSCREEN_RIGHT
].x
= parent
->x
+ parent
->width
- width
- pad
;
135 vps
[screen
][QUICKSCREEN_RIGHT
].width
= width
;
137 vps
[screen
][QUICKSCREEN_LEFT
].height
= vps
[screen
][QUICKSCREEN_RIGHT
].height
140 vps
[screen
][QUICKSCREEN_LEFT
].y
= vps
[screen
][QUICKSCREEN_RIGHT
].y
141 = parent
->y
+ (parent
->height
/2) - char_height
;
143 /* shrink the icons vp by a few pixels if there is room so the arrows
144 aren't drawn right next to the text */
145 if (vp_icons
[screen
].width
> CENTER_ICONAREA_SIZE
*2)
147 vp_icons
[screen
].width
-= CENTER_ICONAREA_SIZE
*2/3;
148 vp_icons
[screen
].x
+= CENTER_ICONAREA_SIZE
*2/6;
150 if (vp_icons
[screen
].height
> CENTER_ICONAREA_SIZE
*2)
152 vp_icons
[screen
].height
-= CENTER_ICONAREA_SIZE
*2/3;
153 vp_icons
[screen
].y
+= CENTER_ICONAREA_SIZE
*2/6;
157 static void quickscreen_draw_text(const char *s
, int item
, bool title
,
158 struct screen
*display
, struct viewport
*vp
)
160 int nb_lines
= viewport_get_nb_lines(vp
);
161 int w
, h
, line
= 0, x
= 0;
162 display
->getstringsize(s
, &w
, &h
);
164 if (nb_lines
> 1 && !title
)
168 case QUICKSCREEN_TOP
:
169 case QUICKSCREEN_BOTTOM
:
170 x
= (vp
->width
- w
)/2;
172 case QUICKSCREEN_LEFT
:
175 case QUICKSCREEN_RIGHT
:
180 display
->puts_scroll(0, line
, s
);
182 display
->putsxy(x
, line
*h
, s
);
185 static void gui_quickscreen_draw(struct gui_quickscreen
*qs
,
186 struct screen
*display
,
187 struct viewport
*parent
)
189 #ifdef HAVE_REMOTE_LCD
190 int screen
= display
->screen_type
;
192 const int screen
= 0;
197 unsigned const char *title
, *value
;
200 display
->set_viewport(parent
);
201 display
->clear_viewport();
202 for (i
=0; i
<QUICKSCREEN_ITEM_COUNT
; i
++)
206 display
->set_viewport(&vps
[screen
][i
]);
207 display
->scroll_stop(&vps
[screen
][i
]);
209 title
= P2STR(ID2P(qs
->items
[i
]->lang_id
));
210 setting
= qs
->items
[i
]->setting
;
211 temp
= option_value_as_int(qs
->items
[i
]);
212 value
= option_get_valuestring((struct settings_list
*)qs
->items
[i
],
213 buf
, MAX_PATH
, temp
);
215 if (vps
[screen
][i
].height
< display
->getcharheight()*2)
218 snprintf(text
, MAX_PATH
, "%s: %s", title
, value
);
219 quickscreen_draw_text(text
, i
, true, display
, &vps
[screen
][i
]);
223 quickscreen_draw_text(title
, i
, true, display
, &vps
[screen
][i
]);
224 quickscreen_draw_text(value
, i
, false, display
, &vps
[screen
][i
]);
226 display
->update_viewport();
229 display
->set_viewport(&vp_icons
[screen
]);
231 display
->mono_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
232 (vp_icons
[screen
].width
/2) - 4, 0, 7, 8);
233 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
234 vp_icons
[screen
].width
- 8,
235 (vp_icons
[screen
].height
/2) - 4, 7, 8);
236 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
], 0,
237 (vp_icons
[screen
].height
/2) - 4, 7, 8);
239 display
->mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
240 (vp_icons
[screen
].width
/2) - 4,
241 vp_icons
[screen
].height
- 8, 7, 8);
243 display
->set_viewport(parent
);
244 display
->update_viewport();
245 display
->set_viewport(NULL
);
248 static void talk_qs_option(struct settings_list
*opt
, bool enqueue
)
250 if (global_settings
.talk_menu
) {
253 talk_id(opt
->lang_id
, true);
254 option_talk_value(opt
, option_value_as_int(opt
), true);
259 * Does the actions associated to the given button if any
260 * - qs : the quickscreen
261 * - button : the key we are going to analyse
262 * returns : true if the button corresponded to an action, false otherwise
264 static bool gui_quickscreen_do_button(struct gui_quickscreen
* qs
, int button
)
272 item
= QUICKSCREEN_TOP
;
276 item
= QUICKSCREEN_LEFT
;
280 item
= QUICKSCREEN_BOTTOM
;
283 case ACTION_QS_RIGHT
:
284 item
= QUICKSCREEN_RIGHT
;
290 option_select_next_val((struct settings_list
*)qs
->items
[item
], invert
, true);
291 talk_qs_option((struct settings_list
*)qs
->items
[item
], false);
294 #ifdef HAVE_TOUCHSCREEN
295 /* figure out which button was pressed...
296 * top is exit, left/right/botton are the respective actions
298 static int quickscreen_touchscreen_button(void)
301 if (action_get_touchscreen_press(&x
, &y
) != BUTTON_REL
)
303 if (y
< vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].y
)
304 return ACTION_STD_CANCEL
;
305 else if (y
> vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].y
+
306 vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].height
)
307 return ACTION_QS_DOWN
;
308 else if (x
< vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].x
+
309 vps
[SCREEN_MAIN
][QUICKSCREEN_LEFT
].width
)
310 return ACTION_QS_LEFT
;
311 else if (x
>= vps
[SCREEN_MAIN
][QUICKSCREEN_RIGHT
].x
)
312 return ACTION_QS_RIGHT
;
313 return ACTION_STD_CANCEL
;
316 static bool gui_syncquickscreen_run(struct gui_quickscreen
* qs
, int button_enter
)
319 struct viewport vp
[NB_SCREENS
];
320 bool changed
= false;
321 /* To quit we need either :
322 * - a second press on the button that made us enter
323 * - an action taken while pressing the enter button,
324 * then release the enter button*/
325 bool can_quit
= false;
328 screens
[i
].set_viewport(NULL
);
329 screens
[i
].stop_scroll();
330 viewport_set_defaults(&vp
[i
], i
);
331 quickscreen_fix_viewports(qs
, &screens
[i
], &vp
[i
]);
332 gui_quickscreen_draw(qs
, &screens
[i
], &vp
[i
]);
334 /* Announce current selection on entering this screen. This is all
335 queued up, but can be interrupted as soon as a setting is
337 cond_talk_ids(VOICE_QUICKSCREEN
);
338 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_LEFT
], true);
339 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_BOTTOM
], true);
340 talk_qs_option((struct settings_list
*)qs
->items
[QUICKSCREEN_RIGHT
], true);
342 button
= get_action(CONTEXT_QUICKSCREEN
,HZ
/5);
343 #ifdef HAVE_TOUCHSCREEN
344 if (button
== ACTION_TOUCHSCREEN
)
345 button
= quickscreen_touchscreen_button();
347 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
349 if(gui_quickscreen_do_button(qs
, button
))
354 gui_quickscreen_draw(qs
, &screens
[i
], &vp
[i
]);
358 else if(button
==button_enter
)
361 if((button
== button_enter
) && can_quit
)
364 if(button
==ACTION_STD_CANCEL
)
367 /* Notify that we're exiting this screen */
368 cond_talk_ids_fq(VOICE_OK
);
372 static inline const struct settings_list
*get_setting(int gs_value
,
373 const struct settings_list
*defaultval
)
375 if (gs_value
!= -1 && gs_value
< nb_settings
&&
376 is_setting_quickscreenable(&settings
[gs_value
]))
377 return &settings
[gs_value
];
380 bool quick_screen_quick(int button_enter
)
382 struct gui_quickscreen qs
;
383 bool oldshuffle
= global_settings
.playlist_shuffle
;
384 int oldrepeat
= global_settings
.repeat_mode
;
386 qs
.items
[QUICKSCREEN_TOP
] =
387 get_setting(global_settings
.qs_item_top
,
388 find_setting(&global_settings
.party_mode
, NULL
));
389 qs
.items
[QUICKSCREEN_LEFT
] =
390 get_setting(global_settings
.qs_item_left
,
391 find_setting(&global_settings
.playlist_shuffle
, NULL
));
392 qs
.items
[QUICKSCREEN_RIGHT
] =
393 get_setting(global_settings
.qs_item_right
,
394 find_setting(&global_settings
.repeat_mode
, NULL
));
395 qs
.items
[QUICKSCREEN_BOTTOM
] =
396 get_setting(global_settings
.qs_item_bottom
,
397 find_setting(&global_settings
.dirfilter
, NULL
));
400 if (gui_syncquickscreen_run(&qs
, button_enter
))
403 settings_apply(false);
404 /* make sure repeat/shuffle/any other nasty ones get updated */
405 if ( oldrepeat
!= global_settings
.repeat_mode
&&
406 (audio_status() & AUDIO_STATUS_PLAY
) )
408 audio_flush_and_reload_tracks();
410 if (oldshuffle
!= global_settings
.playlist_shuffle
411 && audio_status() & AUDIO_STATUS_PLAY
)
413 #if CONFIG_CODEC == SWCODEC
414 dsp_set_replaygain();
416 if (global_settings
.playlist_shuffle
)
417 playlist_randomise(NULL
, current_tick
, true);
419 playlist_sort(NULL
, true);
426 bool quick_screen_f3(int button_enter
)
428 struct gui_quickscreen qs
;
429 qs
.items
[QUICKSCREEN_LEFT
] =
430 find_setting(&global_settings
.scrollbar
, NULL
);
431 qs
.items
[QUICKSCREEN_RIGHT
] =
432 find_setting(&global_settings
.statusbar
, NULL
);
433 qs
.items
[QUICKSCREEN_BOTTOM
] =
434 find_setting(&global_settings
.flip_display
, NULL
);
436 if (gui_syncquickscreen_run(&qs
, button_enter
))
439 settings_apply(false);
443 #endif /* BUTTON_F3 */
445 /* stuff to make the quickscreen configurable */
446 bool is_setting_quickscreenable(const struct settings_list
*setting
)
448 /* to keep things simple, only settings which have a lang_id set are ok */
449 if (setting
->lang_id
< 0 || (setting
->flags
&F_BANFROMQS
))
451 switch (setting
->flags
&F_T_MASK
)
457 return (setting
->RESERVED
!= NULL
);
463 void set_as_qs_item(const struct settings_list
*setting
,
464 enum quickscreen_item item
)
467 for(i
=0;i
<nb_settings
;i
++)
469 if (&settings
[i
] == setting
)
474 case QUICKSCREEN_TOP
:
475 global_settings
.qs_item_top
= i
;
477 case QUICKSCREEN_LEFT
:
478 global_settings
.qs_item_left
= i
;
480 case QUICKSCREEN_RIGHT
:
481 global_settings
.qs_item_right
= i
;
483 case QUICKSCREEN_BOTTOM
:
484 global_settings
.qs_item_bottom
= i
;
486 default: /* shut the compiler up */